• POJ1015


    题目链接:http://poj.org/problem?id=1015

    大概题意:

      法庭要挑选m人陪审团。先随机挑选n个公民,对于每个公民,控辩双方都有各自的“喜好度”p[ ] 和 d[ ],法庭要尽量保证陪审团的m人中控方总喜好度和辩方总喜好度的差值的绝对值尽可能小,如果最佳的结果有多个,那么就选择控辩双方总喜好度最高的那个。

    解题思路:

      日常不会dp题,哭),。。。思路源于网络

      设一个二维数组 dp[i][j], i代表“使用”了几个人,j代表控辩双方喜好度之差,为了避免出现数组下标为负的情况,我们可以把j值的最后再加上20*m。

      状态转移方程:dp[ i+1 ][ j+dat[i+1] ] = min(dp[i+1][ j+dat[i+1] ] , dp[i][j]+sum[i+1] )。sum[i+1] =  p[i+1] + d[i+1], dat[i+1] = p[i+1] - d[i+1] 。

      用vector记录路径,操作方便的出奇。

      Waring: 要把选取哪个人这个循环放在最外层,不然会出现这种bug: 比如说 dp[5][y] = {1,2,3,5,6} = {1,2,3,7,8}, sum[5] + sum[6] = sum[7] + sum[8],  此时程序就有可能选择前面那个{1,2,3,5,6}这五个人,但是sum[5] 很大(大于剩下的所有sum),到了 dp[6][x]的时候,由于第5人已经被选取了,所以他无法再选择第五人,但是如果当初选择的是sum[7]+sum[8],此时就可以选择sum[5]了,很明显,后者会更优,所以程序会出bug。

    AC代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <vector>
     5 using namespace std;
     6 
     7 const int inf=0x7ffffff;
     8 int dp[22][808];
     9 pair<int,int> pd[202];
    10 vector<int> path[22][808];
    11 int main()
    12 {
    13 //    freopen("in.txt","r",stdin);
    14 //    freopen("out.txt","w",stdout);
    15     int n,m,a,b,cases=1,min_n;
    16     while(scanf("%d%d",&n,&m)==2&&n&&m){
    17         for(int i=1;i<=n;i++)
    18             scanf("%d%d",&pd[i].first,&pd[i].second);
    19         min_n=20*m;
    20         for(int i=0;i<=m;i++){
    21             for(int j=0;j<=40*m;j++){
    22                 path[i][j].clear();
    23                 dp[i][j]=-inf;
    24             }
    25         }
    26         dp[0][min_n]=0;
    27         for(int k=1;k<=n;k++){
    28             int dat=pd[k].first-pd[k].second, sum=pd[k].first+pd[k].second;
    29             for(int i=m-1;i>=0;i--){
    30                 for(int j=0;j<=40*m;j++){
    31                     if(dp[i][j]>=0){
    32                         if(dp[i+1][j+dat]<=dp[i][j]+sum){
    33                             dp[i+1][j+dat]=dp[i][j]+sum;
    34                             path[i+1][j+dat]=path[i][j];
    35                             path[i+1][j+dat].push_back(k);
    36                         }
    37                     }
    38                 }
    39             }
    40         }
    41         a=b=0;
    42         for(int i=0;i<=20*m;i++){
    43             if(dp[m][min_n+i]>=0||dp[m][min_n-i]>=0){
    44                 int temp;
    45                 if(dp[m][min_n+i]>dp[m][min_n-i])   temp=min_n+i;
    46                 else    temp=min_n-i;
    47                 for(int l=0;l<m;l++){
    48                     int ind=path[m][temp][l];
    49                     a+=pd[ind].first,b+=pd[ind].second;
    50                 }
    51                 printf("Jury #%d
    ",cases++);
    52                 printf("Best jury has value %d for prosecution and value %d for defence:
    ",a,b);
    53                 for(int l=0;l<m;l++)    printf(" %d",path[m][temp][l]);
    54                 printf("
    
    ");
    55                 break;
    56             }
    57         }
    58 
    59     }
    60     return 0;
    61 }
    View Code
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    Func<T, TResult> 委托的由来和调用和好处(为了高大上,为了白富美)
    $(function(){})和jQuery(function(){})
    把一个类(或者Object)转换成字典
    MVC 控制器向View传值的三种方法
    @html.ActionLink的几种参数格式
    你给老板谈工资,老板给你谈发展.之后发生的事...
    2015-11-5 关于编译的听课笔记
    2015-10-29 韦东山OK6410 第一天课程笔记
    2015-10-26 逻辑运算符使用分析
    2015-10-26 一些位运算符 课程笔记
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/7271554.html
Copyright © 2020-2023  润新知