nyist-部分和问题
来源:互联网 发布:nginx自动跳转首页 编辑:程序博客网 时间:2024/06/08 11:04
部分和问题
- 描述
- 给定整数a1、a2、.......an,判断是否可以从中选出若干数,使它们的和恰好为K。
- 输入
- 首先,n和k,n表示数的个数,k表示数的和。
接着一行n个数。
(1<=n<=20,保证不超int范围) - 输出
- 如果和恰好可以为k,输出“YES”,并按输入顺序依次输出是由哪几个数的和组成,否则“NO”
- 样例输入
4 131 2 4 7
- 样例输出
YES2 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-部分和问题
- nyist oj 1058 部分和问题 (DFS搜索)
- NYIST 47 过河问题
- 过河问题 nyist 47
- nyist 一笔画问题
- nyist 14 会场安排问题
- nyist
- DFS 部分和问题
- 部分和问题
- 多重部分和问题
- 部分和问题
- 部分和问题
- 部分和问题
- nyoj 部分和问题
- nyoj-部分和问题
- nyoj1058部分和问题
- 部分和问题
- nyoj 部分和问题
- Think In Java第九章 接口
- Linux下启动Tomcat显示控制台日志信息
- Android软件盘
- JSONObject.fromObject 日期类型转换问题
- PL/SQL之概述
- nyist-部分和问题
- 多线程——GCD(串行队列)
- SyntaxError: Non-UTF-8 code starting with '\xb2in file.
- 数据库存储过程和触发器
- nginx反向代理配置
- 迷宫问题求解
- 解决输入法无法打字 ,ime禁用问题
- RabbitMQ从入门到精通----环境安装
- PathMeasure