POJhttp://poj.org/problem?id=1564
ZOJhttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=711
HDUhttp://acm.hdu.edu.cn/showproblem.php?pid=1258
今天不好玩。学校网断了,wifi也用不了,爪机当热点还上不去!!!A一题容易吗!然后鼠标更不好使了,果断去买了一个。
瞬间又成穷人。T T
换了个鼠标心情大好~
------------------------------------------回到解放前的分割线------------------------------------------
题目大意:
给定一个数k,然后给出n个数,要求n个数的和要恰好等于k,输出所有可能的结果。
我的方法比较水。。。。直接DFS,然后把全部答案存进数组,最后判断是否重复。
看了别人的有简单的判断重复的方法,不用map不用set不用hash。Orz
if(a[i] != a[i-1])如果a[i]和上一个数相同,那么它不然不会放在上一个数放的位置。
如4 2 2 2 1 目标构成的和是8 那么对于第一个2来说 (递归过程中)会出现4 2 这样的,然后下一个2 可以放在它的后面 ,但就没必要放在第二个位置了。因为两个2是一样的。
我的方法。
#include<cstdio> #include<cstring> const int MAXN=1000+1; int ans[MAXN][MAXN]; int a[MAXN]; bool used[MAXN]={0}; int len,n,target; bool equal(int *a1,int *b) { if(a1[0]!=b[0]) return false; for(int i=1;i<a1[0];i++) { if(a1[i]!=b[i]) return false; } return true; } void dfs(int cur,int sum) { if(sum > target) return; if(target==sum) { int j=1; for(int i=0;i<n;i++) { if(used[i]) ans[len][j++]=a[i]; } ans[len++][0]=j; return; } for(int i=cur;i<n;i++) { if(used[i]) continue; used[i]=true; dfs(i+1,sum+a[i]); used[i]=false; } } int main() { while(scanf("%d%d",&target,&n),n) { len=0; memset(used,0,sizeof(used)); memset(ans,0,sizeof(ans)); for(int i=0;i<n;i++) scanf("%d",&a[i]); dfs(0,0); printf("Sums of %d:\n",target); if(len==0) printf("NONE\n"); else { memset(used,0,sizeof(used)); for(int i=0;i<len;i++) //去重复 { for(int k=i+1;k<len;k++) { if(equal(ans[i],ans[k])) used[k]=true; } } for(int i=0;i<len;i++) { if(used[i]) continue; for(int j=1;j<ans[i][0];j++) { if(j!=1) printf("+"); printf("%d",ans[i][j]); } printf("\n"); } } } }
简单的判断重复:
#include<cstdio> #include<cstring> const int MAXN=15+1; int ans[MAXN]; int a[MAXN]; int len,n,target; bool ok; void dfs(int cur,int sum,int cnt) { if(sum > target) return; if(target==sum) { ok=true; printf("%d",ans[0]); for(int i=1;i<cnt;i++) printf("+%d",ans[i]); printf("\n"); return; } for(int i=cur;i<n;i++) { if(i==cur || a[i] != a[i-1]) { ans[cnt]=a[i]; dfs(i+1,sum+a[i],cnt+1); } } } int main() { while(scanf("%d%d",&target,&n),n) { len=0; ok=false; for(int i=0;i<n;i++) scanf("%d",&a[i]); printf("Sums of %d:\n",target); dfs(0,0,0); if(ok==0) printf("NONE\n"); } }