标签:
题意:给n个数,一开始基数为0,用这n个数依次对基数做加法或减法,使基数不超过k且不小于0,输出最远能运算到的数字个数,输出策略。
解法:dp。dp[i][j]表示做完第i个数字的运算后结果为j的可能性,可能为1,不可能为0,于是得到状态转移方程dp[i][j] = dp[i - 1][j - a[i]] | dp[i - 1][j + a[i]],当被转移的状态不在0~k之间时特判。dp时记录路径。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<limits.h> #include<time.h> #include<stdlib.h> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define LL long long using namespace std; bool dp[1005][1005]; bool path[1005][1005]; int a[1005]; int main() { int n, k; while(~scanf("%d%d", &n, &k)) { for(int i = 1; i <= n; i++) scanf("%d", &a[i]); memset(dp, 0, sizeof dp); memset(path, 0, sizeof path); dp[0][0] = 1; int ans = 0; int pos = 0; for(int i = 1; i <= n; i++) { for(int j = 0; j <= k; j++) { if(j - a[i] < 0 && j + a[i] > k) continue; if(j - a[i] < 0) { dp[i][j] = dp[i - 1][j + a[i]]; path[i][j] = 0; } else if(j + a[i] > k) { dp[i][j] = dp[i - 1][j - a[i]]; path[i][j] = 1; } else { dp[i][j] = (dp[i - 1][j - a[i]] | dp[i - 1][j + a[i]]); if(dp[i - 1][j - a[i]]) path[i][j] = 1; } if(dp[i][j]) { ans = i; pos = j; } } if(ans != i) break; } printf("%d\n", ans); vector <bool> v; for(int i = ans; i > 0; i--) { v.push_back(path[i][pos]); if(path[i][pos]) pos -= a[i]; else pos += a[i]; } int len = v.size(); for(int i = len - 1; i >= 0; i--) { if(v[i]) printf("+"); else printf("-"); } puts(""); } return 0; }
CF GYM 100703G Game of numbers
标签:
原文地址:http://www.cnblogs.com/Apro/p/4685436.html