Poj--1015(DP,状态搜索)
2014-11-28 22:00:10
思路:这题在需要记录状态,一开始没有记录状态瞎搞QAQ。
用dp[i][j]表示选择了i个人,且差值为j时的最优解(即:sigma(p) + sigma(q) 最大)
然后以i做最外层循环枚举,dp[i][j] = max(dp[i - 1][j - (p[k] - q[k])] (1 <= k <= n)
当然在转移时我们得知道dp[i - 1][j - (p[k] - q[k])]中是否已经选了k,其实我们可以用path[i][j]来存储dp[i][j]最后一个取的人,然后dp[i - 1][j - (p[path[i][j]] - q[path[i][j]]),这样一步一步搜索回去看看是否已经选了k
1 /************************************************************************* 2 > File Name: p1015.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Fri 28 Nov 2014 07:22:40 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 27 int n,m; 28 int dp[30][810]; 29 int p[210],q[210]; 30 int path[30][810]; 31 int ans[30],cnt; 32 33 void Print(int a,int b){ 34 int k = path[a][b]; 35 int deta = p[k] - q[k]; 36 if(a > 1) 37 Print(a - 1,b - deta); 38 ans[++cnt] = k; 39 } 40 41 bool Judge(int a,int b,int cur){ 42 while(a >= 1){ 43 int k = path[a][b]; 44 int deta = p[k] - q[k]; 45 if(k == cur) 46 return false; 47 a = a - 1; 48 b = b - deta; 49 } 50 return true; 51 } 52 53 int main(){ 54 int Case = 0; 55 while(scanf("%d%d",&n,&m) != EOF){ 56 if(n == 0 && m == 0) 57 break; 58 for(int i = 1; i <= n; ++i){ 59 scanf("%d%d",p + i,q + i); 60 } 61 memset(path,0,sizeof(path)); 62 memset(dp,-1,sizeof(dp)); 63 dp[0][400] = 0; 64 for(int i = 1; i <= m; ++i){ 65 for(int j = 0; j <= 800; ++j){ 66 for(int k = 1; k <= n; ++k){ 67 int deta = p[k] - q[k]; 68 if(j - deta < 0 || j - deta > 800 || dp[i - 1][j - deta] == -1 69 || !Judge(i - 1,j - deta,k)) 70 continue; 71 if(dp[i - 1][j - deta] + p[k] + q[k] > dp[i][j]){ 72 dp[i][j] = dp[i - 1][j - deta] + p[k] + q[k]; 73 path[i][j] = k; 74 } 75 } 76 } 77 } 78 int tmin = INF,sum,flag; 79 for(int j = 400; j <= 800; ++j){ 80 if(dp[m][j] != -1){ 81 tmin = j - 400; 82 sum = dp[m][j]; 83 flag = j; 84 break; 85 } 86 } 87 for(int j = 400; j >= 0; --j){ 88 if(dp[m][j] != -1){ 89 if(400 - j < tmin || (400 - j == tmin && dp[m][j] > sum)){ 90 tmin = 400 - j; 91 sum = dp[m][j]; 92 flag = j; 93 break; 94 } 95 } 96 } 97 printf("Jury #%d \n",++Case); 98 int base = (sum - tmin) / 2; 99 printf("Best jury has value %d for prosecution and value %d for defence:\n", 100 flag >= 400 ? base + tmin : base,flag >= 400 ? base : base + tmin); 101 cnt = 0; 102 Print(m,flag); 103 sort(ans + 1,ans + cnt + 1); 104 for(int i = 1; i <= cnt; ++i) 105 printf(" %d",ans[i]); 106 printf("\n\n"); 107 } 108 return 0; 109 }