三水和小羽毛玩腻了二十四点,她们决定玩点新东西。
小羽毛给出一个数字和以及 N N N个数字,由三水给出这 N N N个数字计算得出这个数字和的可能。
由于这是一个新游戏,为了不让三水花太多的时间,两人约定只做加法。
小羽毛给出一个数字和 s u m ( s u m ≤ 1000 ) sum(sum≤1000) sum(sum≤1000)。
随后给出 N ( N ≤ 25 ) N(N≤25) N(N≤25)个数字的值,由三水从这 N N N个数字中任意选取(同一个数字只能选取一次)若干,使其和恰好等于 s u m sum sum
第一行是两个数字:数字和 s u m sum sum以及可供三水挑选的数字数量 N N N
第二行有 N N N个正整数 a i a_i ai
输出可能的方案,多个方案则按照字典序输出,每个方案占一行
最后一行输出所有的可行方案总数
输入
3 3
1 1 1
输出
1 2 3
1
输入
5 5
4 1 2 3 1
输出
1 2
1 5
2 4 5
3 4
4
s u m ≤ 1000 sum≤1000 sum≤1000, N N N≤25
看上去是一个01背包,但是emmm这题用dp俺不会做(因为dp回溯只能解出一个最优解。。有没有更好的方法俺也不知道。。。)
因为需要输出所有解,所以这题我用的dfs暴搜+剪枝。
数组a
存储所有数字的值,数组v
标记某个数字是否选中,tol
表示搜索进行到当前情况,已经选中的数字和。
剪枝策略:若当前的数字和tol
已经大于目标值sum
,剪枝。若当前数字已经全部遍历完则返回。
每次对第k
个数字进行选,还是不选的抉择。
如果选中,则v[k]=1
标记选中,然后递归dfs(k+1, tol + a[k])
如果不选,则v[k]=0
标记不选,然后递归dfs(k+1, tol)
注意暴搜的时候,先搜当前数字“选中”的情况,再搜当前数字“不选”的情况。以达到“多个方案按照字典序输出”的目的
#include<bits/stdc++.h>
using namespace std;
const int N = 30;
int a[N], v[N];
int sum, n, res = 0;
void printPlan(){ //输出可行解for(int i = 1; i <= n; i++)if(v[i])cout<<i<<" ";cout<<endl;
}
void dfs(int k, int tol){ //对第k个数字进行抉择,当前已经得到的和为tolif(tol == sum){ //可行解printPlan();res++;return;}if(k > n) //剪枝return;if(tol > sum) //剪枝return;v[k] = 1; //注意先“选择”这个数字dfs(k + 1, tol + a[k]);v[k] = 0; //后“不选”这个数字,以达到字典序输出dfs(k + 1, tol);
}
int main(){cin>>sum>>n;for(int i = 1; i <= n; i++)cin>>a[i];dfs(1, 0); //从第1个数字开始选择,当前数字和为0cout<<res<<endl;return 0;
}
本文发布于:2024-01-28 05:36:48,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063914145173.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |