【经典DFS】NYOJ-1058-部分和问题
2015-05-07 20:05
405 查看
【题目链接:NYOJ-1058】
看到题目难度是2,所以想也没想,直接循环比较。。。结果果然。。。 是错的。#include<cstdio> #include<cstring> int main(){ int n,k; int i,j; int a[22] = {0},num[22] = {0}; scanf("%d%d",&n,&k); for(i = 0;i < n;i++) scanf("%d",&a[i]); int ac = 0,xx = 0; for(i = 0;i < n;i++){ int sum = 0; for(j = i;j < n;j++){ sum += a[j]; num[xx] = a[j]; xx++; if(sum == k){ ac = 1; break; } } if(ac == 1) break; else{ xx = 0; memset(num,0,sizeof(num)); } } if(ac){ printf("YES\n"); for(i = 0;i < xx;i++) printf("%d ",num[i]); }else{ printf("NO"); } return 0; }
以上错误代码,就不回忆为啥错了。。。 贴这儿供着吧。
这题的正确思路是运用DFS
详见:《挑战程序设计》 P30![](http://images.cnitblog.com/blog/478846/201410/282104071907388.jpg)
#include<cstdio> #include<stack> #include<cstring> using namespace std; //部分和问题: const int maxn = 22; stack<int>v; int a[maxn]; int n,m,i,j,k; bool dfs(int i = 0,int sum = 0) //已经从前i项得到了和sum,然后对于i项之后的进行分支 { //停止条件 :如果前n项都计算过了,则返回sum是否与k相等 if(i==n) return sum==k; //选择加或不加a[i] //不加a[i]的情况 if(dfs(i+1,sum)) return true; //加上a[i]的情况 if(dfs(i+1,sum+a[i])){ //若执行该条件,就说明该a[i]符合条件 v.push(a[i]);//压栈 return true; } return false; //无论是否加上a[i]都不能凑成k就返回false; } int main(){ while(~scanf("%d%d",&n,&k)){ for(int i = 0;i < n;i++){ scanf("%d",&a[i]); }if(dfs()){ printf("YES\n"); while(!v.empty()){ int x = v.top(); printf("%d ",x); v.pop(); } printf("\n"); }else printf("NO\n"); } return 0; }
优化:
1.当然也可以用数组代替栈,时间消耗会短8个。2.在状态转移时,如果sum > k,则不需要继续进行了。
(因为是递归,递归的机制就是从上到下,再从下到上返回,所以数组保存的顺序是反向的)
优化代码:
#include<cstdio> #include<stack> using namespace std; stack<int>v; const int maxn = 22; int a[maxn]; //int sta[maxn]; int n,m,k,pos; bool dfs(int i,int sum){ if(i==n) return sum==k; else if(sum > k) return false; //剪枝(这么专业的名词也不知道用的对不对,反正就是优化了一下) if(dfs(i+1,sum)) return true; if(dfs(i+1,sum+a[i])){ //sta[pos++] = a[i]; v.push(a[i]); return true; } return false; } int main(){ while(~scanf("%d%d",&n,&k)){ pos = 0; for(int i = 0;i < n;i++){ scanf("%d",&a[i]); }if(dfs(0,0)){ printf("YES\n"); // for(int i = pos - 1;i >= 0;i--) // printf("%d ",sta[i]); while(!v.empty()){ printf("%d ",v.top()); v.pop(); } printf("\n"); }else printf("NO\n"); } return 0; }
相关文章推荐
- NYOJ 1058 部分和问题(DFS ,经典题)
- NYOJ 1058 部分和问题(经典题目dfs)
- nyoj1058部分和问题(简单基础易上手的dfs)
- NYOJ - 1058 - 部分和问题(DFS+减枝)
- NYOJ 1058 部分和问题 【DFS】
- NYOJ 1058--部分和问题【DFS】
- nyoj 1058 部分和问题 【简单DFS】
- NYOJ 1058部分和问题(dfs+回溯)
- nyoj 1058部分和问题(DFS)
- NYOJ 1058 部分和问题 (DFS)
- NYOJ 1058 部分和问题 【DFS】
- NYOJ--1058--dfs--部分和问题
- nyoj 1058 部分和问题 【DFS】
- NYOJ 1058部分和问题(DFS)
- nyoj--1058 部分和问题(dfs)
- NYOJ-1058- 部分和问题(DFS)
- NYOJ 1058 部分和问题(dfs)
- NYOJ 1058 部分和问题(DFS)
- nyoj1058 部分和问题 dfs
- NYOJ1058. 部分和问题(基础DFS)