题解:UVA574 Sum It Up
这种题怎么评的绿。
Problem
给定一个长度为 的序列 ,对于每一个 可以选或不选,要求输出所有被选的 的和为 的方案。输出要求:所有答案呈字典序降序且不重复,在一组答案 要降序。如:10+5+3 是符合要求的,但是 3+10+5 不符合要求。
多组数据,以两个 结束,。
Solution
Idea
首先要降序,不妨把 降序排序,这样就能保证 一定是降序的,这和我们的算法有关。
暴力 dfs 每一个数选不选。选的话就把它加到答案里面去并更新和。
然后只要在最后判断是否不重复即可。
如何判断不重复?我们要把以往的答案存起来。注意为了防止多测不清空导致的错误,我们把没有用到的答案数组 的元素值全部归为 。然后剩下的就好做了。
另外一个剪枝:如果还没有枚举完,但是和已经比 大了,就排除掉,不用再 dfs 了。
Code
#include<bits/stdc++.h>
using namespace std;
int n,t,a[15];
int p[15],ans[1025][15],len,fl;
int cnt;
bool check(){
for(int i=1;i<=cnt;i++){
bool f=1;
for(int j=1;j<=12;j++){
if(ans[i][j]!=p[j]){
f=0;
break;
}
}
if(f)return true;
// printf("%d\n",i);
}
return false;
}
void dfs(int now,int sum){
if(sum>t)return;
if(now==n+1){
if(sum!=t)return;
for(int i=len+1;i<=12;i++)p[i]=-1;
if(check())return;
cnt++;
ans[cnt][1]=p[1];
fl=1;
for(int i=2;i<=len;i++){
ans[cnt][i]=p[i];
}
for(int i=len+1;i<=12;i++){
ans[cnt][i]=-1;
}
return;
}
else{
dfs(now+1,sum);
p[++len]=a[now];
dfs(now+1,sum+a[now]);
--len;
}
}
bool cmp(int _,int __){
return _>__;
}
int main() {
while(1) {
cnt=0;
len=0;
fl=0;
scanf("%d%d",&t,&n);
if(n==0&&t==0)break;
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
}
printf("Sums of %d:\n",t);
sort(a+1,a+n+1,cmp);
dfs(1,0);
if(!fl)printf("NONE\n");
else{
for(int i=cnt;i>=1;i--){
printf("%d",ans[i][1]);
for(int j=2;j<=12;j++){
if(ans[i][j]==-1)break;
printf("+%d",ans[i][j]);
}
printf("\n");
}
}
}
return 0;
}

浙公网安备 33010602011771号