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

Codeforces 689 C The Values You Can Make(dp)

2016-07-08 16:11 519 查看
题意:

给你一些硬币,让你选出一个子集的总价值和为k,然后对于一个选出的子集,除了可以组成k以外,还可以在选出的子集中选出一些其他的价值。问你所有的选出的子集一共可以得到多少种价值。

对于这个,因为tag是动态规划,所以就往上面思考,但是找不到一个一个可行的状态。看过题解才明白,一个很机智的状态。

dp[i][j][k]表示前i个硬币组成了价值为j的一个子集并且里面可以得到k大小面额的情况是否存在。那么对于一个硬币,总共有三个转移,1、这个硬币避灾选出的子集中;2、这个硬币在选出的子集中但是不在拿出的子集中即子集的子集;3、这个硬币在所有的集合中。

所以dp[i][j][k]=dp[i−1][j][k]‖dp[i−1][j−c[i][k]‖dp[i−1][j−c[i]][k−c[i]]。我们在得到这个之后,既可以去尝试每一个可能的值是否存在。具体看代码。

代码:

//
//  Created by  CQU_CST_WuErli
//  Copyright (c) 2016 CQU_CST_WuErli. All rights reserved.
//
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <algorithm>
#include <sstream>
#define CLR(x) memset(x,0,sizeof(x))
#define OFF(x) memset(x,-1,sizeof(x))
#define MEM(x,a) memset((x),(a),sizeof(x))
#define BUG cout << "I am here" << endl
#define lookln(x) cout << #x << "=" << x << endl
#define SI(a) scanf("%d", &a)
#define SII(a,b) scanf("%d%d", &a, &b)
#define SIII(a,b,c) scanf("%d%d%d", &a, &b, &c)
const int INF_INT=0x3f3f3f3f;
const long long INF_LL=0x7f7f7f7f;
const int MOD=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
typedef long long  ll;
using namespace std;

int n, k;
int c[550];
int dp[2][555][555];

int main(int argc, char const *argv[]) {
#ifdef LOCAL
freopen("C:\\Users\\john\\Desktop\\in.txt","r",stdin);
// freopen("C:\\Users\\john\\Desktop\\out.txt","w",stdout);
#endif
while (SII(n, k) == 2) {
for (int i = 1; i <= n; i++)
SI(c[i]);
CLR(dp);
dp[0][0][0] = 1;
for (int i = 1; i <= n; i++) {
int now = i % 2;
int last = now ^ 1;
for (int j = 0; j <= k; j++) {
for (int s = 0; s <= j; s++) {
dp[now][j][s] |= dp[last][j][s];
if (j >= c[i]) dp[now][j][s] |= dp[last][j - c[i]][s];
if (s >= c[i]) dp[now][j][s] |= dp[last][j - c[i]][s - c[i]];
}
}
}
vector<int> ans;
for (int i = 0; i <= k; i++)
if (dp[n % 2][k][i]) ans.push_back(i);
cout << (int)ans.size() << endl;
for (int i = 0; i < ans.size(); i++)
cout << ans[i] << ' ';
cout << endl;
}
return 0;
}
/*
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\  =  /O
____/`---'\____
.'  \|     |//  `.
/  \|||  :  |||//  \
/  _||||| -:- |||||-  \
|   | \\  -  /// |   |
| \_|  ''\---/''  |   |
\  .-\__  `-`  ___/-. /
___`. .'  /--.--\  `. . __
."" '<  `.___\_<|>_/___.'  >'"".
| | :  `- \`.;`\ _ /`;.`/ - ` : | |
\  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
佛祖保佑        永无BUG
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划 codeforces dp