zoukankan      html  css  js  c++  java
  • Jury Compromise POJ

    题意:从 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
    ", kase++ );
    48         printf( "Best jury has value %d for prosecution and value %d for defence:
    ", sumD,sumP);
    49         for( i=0; i < m; i++ )
    50             printf( " %d", path[m][fix+temp][i]+1);
    51         printf("
    
    ");
    52         
    53         
    54     }
    55     return 0;
    56 }
  • 相关阅读:
    标题栏外区域拖动窗体
    搜索引擎技术核心揭密
    用C#实现木马程序(转载)
    DotNet里的控件数组
    RECORDNUMBER应用之控制每页显示行数及隔行换色
    搜索引擎技术学习
    VB里面操作Excel(居然比C#强)
    第三代搜索引擎技术与P2P
    C# 用API播放声音
    如何判断ExecuteScalar()得到的结果是否有记录
  • 原文地址:https://www.cnblogs.com/ttttttttrx/p/10274095.html
Copyright © 2011-2022 走看看