您的位置:首页 > 其它

【经典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



#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;
}


    

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: