• POJ1015-Jury Compromise


    题意:给你n个数对(d, p),挑选出m个,使得sigma(d)sigma(p)的差最小,如果有多种选法,选sigma(d)+sigma(p)最大的

    dp(i,j)表示选出i个人,差值为jsigma(d)+sigma(p)的最大值,初始为-1,那么最后的答案就是使dp(m,j)>=0j的最小值。那么如何求dp(i,j)呢?肯定是在选出m-1个人的基础上再选一个人。设是在dp(i-1,x)的基础上选出的,那么必须要存在一个数对满足x+d-p=j且这个数对没有在dp(i-1,x)方案中出现过。那么如何知道有没有出现过呢?可以用数组path[i][j]表示方案dp(i,j)dp(i-1,x)基础上再选出的那个人的编号。所以可以从path[i][j]往回寻找方案中所有已经被选过的人,排除即可。最后需要注意的就是差值会小于0,给它加上一个修正值fix,变成非负数就行了。

     1 #include <iostream>
     2 #include <sstream>
     3 #include <fstream>
     4 #include <string>
     5 #include <map>
     6 #include <vector>
     7 #include <list>
     8 #include <set>
     9 #include <stack>
    10 #include <queue>
    11 #include <deque>
    12 #include <algorithm>
    13 #include <functional>
    14 #include <numeric>
    15 #include <iomanip>
    16 #include <climits>
    17 #include <new>
    18 #include <utility>
    19 #include <iterator>
    20 #include <complex>
    21 #include <cstdio>
    22 #include <cstdlib>
    23 #include <cstring>
    24 #include <cctype>
    25 #include <cmath>
    26 #include <ctime>
    27 using namespace std;
    28 
    29 const int maxn = 210;
    30 const int maxm = 25;
    31 const int fix = 400;
    32 
    33 int n, m;
    34 int d[maxn], p[maxn];
    35 int dp[maxm][2*fix+10];
    36 int path[maxm][2*fix+10];
    37 int ans[maxm];
    38 
    39 int main()
    40 {
    41     int kase = 1;
    42     while (scanf("%d%d", &n, &m) == 2 && (n || m))
    43     {
    44         for (int i = 0; i < n; ++i)
    45             scanf("%d%d", &d[i], &p[i]);
    46         memset(dp, -1, sizeof(dp));
    47         memset(path, 0, sizeof(path));
    48         dp[0][fix] = 0;
    49         for (int i = 0; i < m; ++i)
    50             for (int j = 0; j < 2*fix+10; ++j)
    51                 if (dp[i][j] >= 0)
    52                     for (int k = 0; k < n; ++k)
    53                         if (dp[i][j]+d[k]+p[k] > dp[i+1][j+d[k]-p[k]])
    54                         {
    55                             int ti = i, tj = j;
    56                             while (ti > 0 && path[ti][tj] != k)
    57                             {
    58                                 tj -= d[path[ti][tj]] - p[path[ti][tj]];
    59                                 ti--;
    60                             }
    61                             if (!ti)
    62                             {
    63                                 dp[i+1][j+d[k]-p[k]] = dp[i][j] + d[k] + p[k];
    64                                 path[i+1][j+d[k]-p[k]] = k;
    65                             }
    66                         }
    67         int dj = 0;
    68         while (dp[m][fix-dj] == -1 && dp[m][fix+dj] == -1)
    69             dj++;
    70         int k = dp[m][fix-dj] > dp[m][fix+dj] ? fix-dj : fix+dj;
    71         printf("Jury #%d
    ", kase++);
    72         printf("Best jury has value %d for prosecution and value %d for defence:
    ", (k-fix+dp[m][k])/2, (dp[m][k]-k+fix)/2);
    73         for (int i = 0; i < m; ++i)
    74         {
    75             ans[i] = path[m-i][k];
    76             k -= d[ans[i]] - p[ans[i]];
    77         }
    78         sort(ans, ans+m);
    79         for (int i = 0; i < m; ++i)
    80             printf("%d%c", ans[i]+1, i==m-1?'
    ':' ');
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    选项菜单-OptionMenu
    Android Studio教程
    android 使用layer-list
    JavaScript OOP 学习总结
    Android应用中网络请求库Volley的使用
    Android应用中网络请求库Volley的介绍
    Android UI: LinearLayout中layout_weight 属性的使用规则
    Robot Framework 培训
    Begin :SWIFT 基本语法
    树莓派raspberrypi系统安装docker以及编译nginx和php镜像
  • 原文地址:https://www.cnblogs.com/godweiyang/p/4913868.html
Copyright © 2020-2023  润新知