您的位置:首页 > 产品设计 > UI/UE

7_6_M题 The Values You Can Make题解[Codeforces 687C](DP)

2016-07-10 22:36 501 查看
题目链接

简单题意

有n枚硬币,面值不尽相同,要给出价值和为k的硬币,问用价值和为k的硬币能组合出多少种不同的面值?

思路

动规 dp[i][k][s] 代表前 i 枚硬币中,价值和为 k 的子集能否组合出价值为 s 面值。

设硬币的面值为coin[i] 则转移方程为

dp[i][k][s]=dp[i−1][k][s]∣dp[i−1][k−coin[i]][s]∣dp[i−1][k−coin[i]][s−coin[i]]

初始化 dp[0][0][0]=true

代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;

const int maxn = 5e2+5;
bool dp[2][maxn][maxn];
int coin[maxn];
queue<int> ans;
int main(){
int n ,m;
scanf("%d %d", &n,&m);
for(int i = 1 ; i <= n ; i ++)
scanf("%d", coin + i);
dp[0][0][0] = 1;
for(int i = 1 ; i <= n ; i ++){
for(int j = 0 ; j <= m ; j ++){
for(int k = 0 ; k <= j ; k ++){
dp[i%2][j][k] |= dp[(i-1)%2][j][k];
if(j >= coin[i]) dp[i%2][j][k] |= dp[(i-1)%2][j-coin[i]][k];
if(k >= coin[i]) dp[i%2][j][k] |= dp[(i-1)%2][j-coin[i]][k-coin[i]];
}
}
}
for(int i = 0 ; i <= m ; i ++)
if(dp[n%2][m][i]) ans.push(i);
printf("%d\n", ans.size());
while(!ans.empty()){
printf("%d ",ans.front());
ans.pop();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: