Jury Compromise POJ - 1015 dp (标答有误)背包思想

题意:从 n个人里面找到m个人  每个人有两个值  d   p     满足在abs(sum(d)-sum(p)) 最小的前提下sum(d)+sum(p)最大

思路:dp[i][j]  i个人中  和是 j       运用背包的思想  二维背包 i是人数容量,人数要符合背包思想,每次只插入一个,逆序枚举

    j是sum(d)+sum(p) 

注意:这题的标准解法有误:https://blog.csdn.net/lyy289065406/article/details/6671105 这是有误的解法

错误由 POJ dicuss 提出:

也就是说  如果    存在和1 3 5  <2 4 6 但是差值相同    但是1 3 5 6是最大的  然而这时候 dp[3][j]的路径是2 4 6的路径  就不能再选出 6来更新1 3 5 所以就会有后效性 dp不成立  

正解参考:https://blog.csdn.net/glqac/article/details/22687243

 正解运用了背包的思想  进行二维化  第一维表示背包人数容量 第二维表示和 这样能不重不漏把所有情况都枚举了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 const int maxn=900;
 7 int dp[25][maxn],sub[250],Plus[250];
 8 vector<int>path[25][maxn];
 9 int main(){
10     int n,m,kase=1;
11     while(scanf("%d%d",&n,&m)==2){
12         if(n+m==0)break;
13         for(int i=0;i<m;i++){
14             for(int j=0;j<maxn;j++){
15                 path[i][j].clear();
16             }
17         }
18         memset(dp,-1,sizeof(dp));
19         int a,b;
20         for(int i=0;i<n;i++){
21             scanf("%d%d",&a,&b);
22             sub[i]=a-b;
23             Plus[i]=a+b;
24         }
25         int fix=20*m;
26         dp[0][fix]=0;
27         for(int k=0;k<n;k++){
28             for(int i=m-1;i>=0;i--){
29                 for(int j=0;j<fix*2;j++){
30                     if(dp[i][j]>=0){
31                         if(dp[i+1][j+sub[k]]<dp[i][j]+Plus[k]){
32                             dp[i+1][j+sub[k]]=dp[i][j]+Plus[k];
33                             path[i+1][j+sub[k]]=path[i][j];
34                             path[i+1][j+sub[k]].push_back(k);
35                         }
36                     }
37                 }
38             }
39         }
40         int i;
41         for( i=0;dp[m][fix-i]==-1&&dp[m][fix+i]==-1;i++);
42         int temp=dp[m][fix+i]>dp[m][fix-i]?i:-i;
43         int sumD = ( dp[m][fix+temp] + temp )/2;
44         int sumP = ( dp[m][fix+temp] - temp )/2;
45         //辩方总值 = (辨控和+辨控差+修正值)/2
46         //控方总值 = (辨控和-辨控差+修正值)/2
47          printf( "Jury #%d\n", kase++ );
48         printf( "Best jury has value %d for prosecution and value %d for defence:\n", sumD,sumP);
49         for( i=0; i < m; i++ )
50             printf( " %d", path[m][fix+temp][i]+1);
51         printf("\n\n");
52         
53         
54     }
55     return 0;
56 }

 

posted @ 2019-01-15 20:22  tttttttttrx  阅读(147)  评论(0编辑  收藏  举报