部分和问题

时间限制:1000 ms  |  内存限制:65535 KB
难度:2
描述
给定整数a1、a2、.......an,判断是否可以从中选出若干数,使它们的和恰好为K。

输入
首先,n和k,n表示数的个数,k表示数的和。
接着一行n个数。
(1<=n<=20,保证不超int范围)
输出
如果和恰好可以为k,输出“YES”,并按输入顺序依次输出是由哪几个数的和组成,否则“NO”
样例输入
4 13
1 2 4 7
样例输出
YES
2 4 7
来源
经典题目

这道题是水题?

我咋觉得一点也不水~~~~~

可能是我太水,我自己写的代码  发现了很多问题,结果都出现不了 下面我一点一点分析

#include<stdio.h>
#include<string.h>
bool flag;
int a[30],b[30],sum;
int n,k,j;
void dfs(int x)
{sum+=a[x];if(sum==k){flag=true;return;}if(sum>k){sum-=a[x];return;}if(sum<k){b[j++]=a[x];dfs(x+1);}
}
int main()
{while(scanf("%d%d",&n,&k)!=EOF){j=0,sum=0;memset(b,0,sizeof(b));for(int i=0; i<=n; i++){scanf("%d",&a[i]);}for(int i=0; i<=n; i++){dfs(i);}if(flag){printf("YES\n");for(int i=0; a[i]!=0; i++){printf("%d ",b[i]);}printf("\n");}else{printf("NO\n");}}
}

这是我第一次的代码  都无法输出结果

递归都写错 了  几乎没有一点对的(初学见谅)

原先的思路是把数存进b【30】中  但是发现麻烦  不如直接判断这个数用没,没用表示0 用了表示1

而且这样写递归  不容易看对错

还有一个问题  我在递归里面没有用for循环,代替的在主函数里用了

(说说for循环的作用);如果没有for循环 那么我只是简单递归 这个数加不加  如样例   1 2 4 7  先1  接着递归 2 继续 4 还小于13  继续7 变成14  好了不满足条件

我返回  只有 1 2 4    根据代码 我继续返回 1 2  继续返回  1 最后没了  那就没答案了

但是  我for循环加在主函数后  只是在  第一个数选择  1不行时选择  第一个数为2   选择时  中间不会跳过数字  如   4  17         1 7 3  10   这组样例  1开头不行  我7开头  递归3  不够 递归 10  多了  返回  再返回  最后又是无解

for在里面就没有这种情况

for(int i=pos;i<n;i++){  sum+=a[i];  visit[i]=1;  dfs(i+1);  sum-=a[i];  visit[i]=0;  }  

最后修改  成这样

#include <cstdio>
#include <cstring>
using namespace std;
int a[30],visit[30],n,k,sum;
bool flag;
void dfs(int pos)
{if(flag==true)return ;if(sum>k){return;}if(sum==k){flag=true;return;}for(int i=pos; i<n; i++){sum+=a[i];visit[i]=1;//printf("%d %d %d\n",pos,i,sum);/*for(int k=0; k<n; k++){printf("%d ",visit[k]);}printf("\n");*/dfs(i+1);if(!flag){sum-=a[i];visit[i]=0;}}
}
int main()
{int i;while(scanf("%d%d",&n,&k)!=EOF){for(i=0; i<n; i++)scanf("%d",&a[i]);memset(visit,0,sizeof(visit));flag=false;dfs(0);if(!flag)printf("NO\n");else{printf("YES\n");for(int j=0; j<n; j++){if(visit[j]==1){printf("%d ",a[j]);}}}}return 0;
}

但是还是有问题  样例能过 但是WA

下面测试一组数据

5 9

1 2 3 4 10

输出结果竟然是

2 3 4 10

明显  10时多余的

为啥??????

if(!flag){sum-=a[i];visit[i]=0;}

不知道注意到这没

我是在主函数外判断flag  再输出结果

但是有一个问题  我递归的时候  最后递归结束的时候  会把我做的标记全部消除····

最后只知道YES  没法知道值

为了不让最后递归的时候 把我标记全清零

那么我记  如果找到答案了  我就回溯的时候就不再清我的标记

但是  又出现个小尾巴 ,我递归10时把10标记了

但是我找到答案了  又没有消除!!!那么成小尾巴了

怎么办  那我只好找到答案直接赶紧趁热  输出

要不递归问题多

void dfs(int pos)
{if(flag==true){printf("YES\n");for(int j=0; j<n; j++){if(visit[j]==1){printf("%d ",a[j]);}}return ;}if(sum>k){return;}if(sum==k){flag=true;return;}for(int i=pos; i<n; i++){sum+=a[i];visit[i]=1;dfs(i+1);if(!flag){sum-=a[i];visit[i]=0;}}
}

只把递归函数变了

哈哈哈  没问题了~!!!

求豆麻袋   输出的结果由于我递归回去的时候  flag=true  一直成立  我就会输出很多组值~~~~~~

天天天天啊~~~~

再想  我让以第一次跟后面的都不一样

#include <cstdio>
#include <cstring>
using namespace std;
int a[30],visit[30],n,k,sum;
bool flag;
void dfs(int pos)
{if(sum==k){flag=true;printf("YES\n");for(int j=0; j<n; j++){if(visit[j]==1){printf("%d ",a[j]);}}printf("\n");return ;}if(sum>k){return;}for(int i=pos; i<n; i++){sum+=a[i];visit[i]=1;printf("%d %d %d\n",pos,i,sum);for(int k=0; k<n; k++){printf("%d ",visit[k]);}printf("\n");dfs(i+1);if(!flag){sum-=a[i];visit[i]=0;}}
}
int main()
{int i;while(scanf("%d%d",&n,&k)!=EOF){for(i=0; i<n; i++)scanf("%d",&a[i]);memset(visit,0,sizeof(visit));flag=false;dfs(0);if(!flag)printf("NO\n");}return 0;
}

提交  WA  !!!

还有个问题  第二次输入的值不正确

#include <cstdio>
#include <cstring>
using namespace std;
int a[30],visit[30],n,k,sum;
bool flag;
void dfs(int pos)
{if(sum==k){flag=true;printf("YES\n");for(int j=0; j<n; j++){if(visit[j]==1){printf("%d ",a[j]);}}printf("\n");return ;}if(sum>k){return;}for(int i=pos; i<n; i++){sum+=a[i];visit[i]=1;/*printf("%d %d %d\n",pos,i,sum);for(int k=0; k<n; k++){printf("%d ",visit[k]);}printf("\n");*/dfs(i+1);sum-=a[i];visit[i]=0;}
}
int main()
{int i;while(scanf("%d%d",&n,&k)!=EOF){sum=0;for(i=0; i<n; i++)scanf("%d",&a[i]);memset(visit,0,sizeof(visit));flag=false;dfs(0);if(!flag)printf("NO\n");}return 0;
}

AC代码   发现不同没

没错

if(!flag){sum-=a[i];visit[i]=0;}

这里改动一下~~~本来是为了防止回去时候把标记清除了的

但是我已经提前输出结果了  标记无所谓了    没去掉

重点  他影响了第二次的运行  这个  为什么影响  大家下去自己思考

真的第一次写这么长的博客 记录我写一道题的经理

真的卡在这道题上太多时间~~~~

不过收获很大  时间用的还是很值得的

总结;

做题不要看网上代码

以前不会直接百度代码  不知道每一个代码都有这么多自己想不到的门道

先自己 写一个代码  (自己认为正确的)

即使出不来结果也无所谓了  我们慢慢改

做一道会一道

nyist-部分和问题相关推荐

  1. 部分和模板的复杂嵌套

    本文翻译自:Complex nesting of partials and templates My question involves how to go about dealing with co ...

  2. java 分班_J 分班(class)(NYIST 2019年校赛)

    J 分班(class)(NYIST 2019年校赛) 内存限制:256MB 时间限制:1s Special Judge: No 题目描述: jsb 是 XX 市第一中学的校长.一轮模拟考试结束后,js ...

  3. 数论 - 简单数位推理 --- NYIST 514

    Problem's Link:http://acm.nyist.net/JudgeOnline/problem.php?pid=514 Mean: 给你一个l和r,求出在这个范围内的1的个数. ana ...

  4. 部分和问题 (dfs搜索 尺取)

    部分和问题 给定整数a1, a2, a3, a4,  ..........   ,  an  ,判断是否可以从中取出若干个数,使得他们的和恰好为k  . 1  <= n <= 20 测试数 ...

  5. nyist --- 组队赛(四)

    本次已是第四次组队赛了,感觉状态不太好,队友之间配合的不是那么默契,A,B,C,G,F,H题都是比较水的题目,不过在做题的过程中 总是让人感觉出乎意外,第一题即wa了一次,紧接着第二题wa了3次,英文 ...

  6. nyist -- 组队赛(二)

    比赛链接:http://acm.nyist.net/JudgeOnline/problemset.php?cid=193 题解报告:http://pan.baidu.com/s/1ntwPVkd 代码 ...

  7. 计算机上开发和运行应用程序与操作系统无关,计算机期中测验理论部分和答案-C.doc...

    计算机期中测验理论部分和答案-C 一.判断题(共10分,正确填写T,反之填写F) 1.Cache和主存储器虽然都是用半导体芯片作为存储介质,但前者使用SRAM,后者使用DRAM,前者比后者的存取速度快 ...

  8. Android应用程序的组成部分和Manifest文件(转)

    Android应用程序由松散耦合的组件组成,并使用应用程序Manifest绑定到一起:应用程序Manifest描述了每一组件和它们之间的交互方式,还用于指定应用程序元数据.其硬件和平台要求.外部库以及 ...

  9. 数据结构与算法之打印两个有序链表公共部分和判断一个链表是否具有回文结构

    数据结构与算法之打印两个有序链表公共部分和判断一个链表是否具有回文结构 目录 打印两个有序链表公共部分 判断一个链表是否具有回文结构 1. 打印两个有序链表公共部分 1.问题描述 思路:Node1和N ...

  10. 习题2-3 求平方与倒数序列的部分和

    本题要求对两个正整数m和n(m≤n)编写程序,计算序列和m​2​​+1/m+(m+1)​2​​+1/(m+1)+⋯+n​2​​+1/n. 输入格式: 输入在一行中给出两个正整数m和n(m≤n),其间以 ...

最新文章

  1. PostgreSQL免安装部署方法
  2. PHP中的 fastcgi_finish_request();
  3. linux 制作box文件夹,用busybox制作自己简易的根文件系统
  4. Colourshell:给 shell 命令着色
  5. html的article标签,介绍一个html5做的网站,以及article标签的用法
  6. Bruce的程序员语录
  7. 做了5年测试连一门语言都没学?逆袭后拿到3个超22K offer!
  8. vue项目打包,生成dist文件夹,如何修改文件夹的名字
  9. 使用Connector / Python查询MySQL数据
  10. 从shell(终端)中退出python
  11. 【MM小贴士】SAP 批次双单位 CWM 的使用演示
  12. eeupdate使用说明_UNRAID中文插件分享以及部分问题解决方案
  13. Spring入门学习推荐
  14. [转载]每天早晨含姜片含出三大奇迹/姜的二十种食疗功/生姜克
  15. 波峰波谷(凸点凹点)的检测算法
  16. python 二进制与十进制之间的转换
  17. Win10 DISM 清理 C盘的 WinSXS 文件夹
  18. 怎么求最大公因数和最小公倍数
  19. Android开发的单词本APP项目介绍及源码(大作业)
  20. jenkins环境配置

热门文章

  1. kindle导出电子书pc_使用Kindle for PC在计算机上阅读Kindle电子书
  2. 中科院分区表中分区上升的TOP期刊, 最快仅1-2个月录用
  3. Linux 和UNIX 的新手培训教程
  4. java获取下载链接文件流并上传至OSS
  5. 题目26: 孪生素数问题
  6. Quill编辑器操作实例详解
  7. c语言输入f1到f11,我来告诉你:电脑键盘的F1至F12正确用处
  8. win10 安装k8s
  9. 数组_二维数组的初始化方式
  10. CELLID的定位技术