题解:UVA574 Sum It Up

这种题怎么评的绿。

Problem

给定一个长度为 nn 的序列 aa,对于每一个 aia_i 可以选或不选,要求输出所有被选的 aia_i 的和为 tt 的方案。输出要求:所有答案呈字典序降序且不重复,在一组答案 ansans 要降序。如:10+5+3 是符合要求的,但是 3+10+5 不符合要求。

多组数据,以两个 00 结束,n12n\le 12

Solution

Idea

首先要降序,不妨把 aa 降序排序,这样就能保证 ansans 一定是降序的,这和我们的算法有关。

暴力 dfs 每一个数选不选。选的话就把它加到答案里面去并更新和。

然后只要在最后判断是否不重复即可。

如何判断不重复?我们要把以往的答案存起来。注意为了防止多测不清空导致的错误,我们把没有用到的答案数组 ansans 的元素值全部归为 1-1。然后剩下的就好做了。

另外一个剪枝:如果还没有枚举完,但是和已经比 tt 大了,就排除掉,不用再 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;
}
posted @   Weslie_qwq  阅读(2)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示