zoukankan      html  css  js  c++  java
  • POJ 1015 陪审团问题

    题意略。

    思路:

    这个题目开始我本来打算用个二维dp,令dp[ i ][ j ]为考虑前i个人,有j个名额的时候,我所能获取的最小差,后来发现不好转移。因为dp[ i ][ j ]有可能是+2,

    也有可能是-2,这两种值对我以后的求解可能都有用。后来想再添加一维,dp[ i ][ j ][ 0 ]表示正值的最小,dp[ i ][ j ][ 1 ]表示负值的最小(绝对值的最小)。

    这样dp逻辑又很复杂。最后参考了网上的解法,于是将状态定义为:

    dp[ i ][ j ][ k ]表示在前i个人里考虑,有j个名额,使得sigma(p) - sigma(d)为k时,我所能获得的sigma(p + d)的最大值。

    状态转移方程:dp[ i ][ j ][ k ] = max(dp[i - 1][ j ][ k ] , dp[i - 1][j - 1][k - p[i] + d[i] ] + p[ i ] + d[ i ])

    只可惜我做题时只想到了正负值的问题,没有更进一步将正负值直接确定为差值,然后dp对象为p + d,从而满足题目中的第二个条件。

    有时dp对象可以是次要条件,而不是首要条件,换一种方向去思考问题。

    内存很紧张

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn1 = 25;
    const int maxn2 = 205;
    const int maxn3 = 805;
    const int mid = maxn3>>1;
    const int F = 0x3f;
    const int INF = 0x3f3f3f3f;
    
    struct node{
        int peo,place,sub;
        node(int peo = 0,int place = 0,int sub = 0){
            this->peo = peo,this->place = place,this->sub = sub;
        }
    };
    
    int p[maxn2],d[maxn2],dp[maxn2][maxn1][maxn3],store[maxn2],n,m;
    node path[maxn2][maxn1][maxn3];
    
    int main(){
        int cas = 1;
        while(scanf("%d%d",&n,&m) == 2 && (n + m)){
            for(int i = 1;i <= n;++i) scanf("%d%d",&p[i],&d[i]);
            int total = 20 * m;
            int low = mid - total,up = mid + total;
            
            for(int i = 0;i <= n;++i){
                for(int j = 0;j <= m;++j){
                    for(int k = low;k <= up;++k){
                        dp[i][j][k] = -1;
                        path[i][j][k] = node(-1,-1,-1);
                    }
                }
            }
            
            for(int i = 0;i <= n;++i) dp[i][0][mid] = 0;
            
            for(int i = 1;i <= n;++i){
                int bound = min(i,m);
                for(int j = 1;j <= bound;++j){
                    for(int k = low;k <= up;++k){
                        int part1 = dp[i - 1][j][k];
                        int part2 = (k - p[i] + d[i] < low || k - p[i] + d[i] > up || dp[i - 1][j - 1][k - p[i] + d[i]] == -1) ? -1 : dp[i - 1][j - 1][k - p[i] + d[i]] + p[i] + d[i];
                        dp[i][j][k] = max(part1,part2);                    
                        if(part1 == -1 && part2 == -1) continue;
                        if(part1 > part2) path[i][j][k] = node(i - 1,j,k);
                        else path[i][j][k] = node(i - 1,j - 1,k - p[i] + d[i]);
                    }
                }
            }
            int idx;
            for(int i = 0;i <= total;++i){
                int lft = mid - i,rht = mid + i;
                int maxx = max(dp[n][m][lft],dp[n][m][rht]);
                if(maxx == -1) continue;
                if(maxx == dp[n][m][lft]) idx = lft;
                else idx = rht;
                if(maxx != -1) break;
            }
            int tail = 0;
            for(int i = n,j = m,k = idx;i != -1;){
                node temp = path[i][j][k];
                int nxti = temp.peo;
                int nxtj = temp.place;
                int nxtk = temp.sub;
                if(nxti == -1) break;
                if(nxtj < j) store[tail++] = i;
                i = nxti,j = nxtj,k = nxtk;
            }
            int ans1 = 0,ans2 = 0;
            for(int i = 0;i < tail;++i){
                ans1 += p[store[i]];
                ans2 += d[store[i]];
            }
            printf("Jury #%d
    ",cas++);
            printf("Best jury has value %d for prosecution and value %d for defence:
    ",ans1,ans2);
            for(int i = tail - 1;i >= 0;--i) printf(" %d",store[i]);
            printf("
    
    ");
        }
        return 0;
    }
    
    /*
    4 2 
    1 2 
    2 3 
    4 1 
    6 2 
     
    10 5  
    3  8 
    15  8 
    11  8 
    7  8 
    1  8 
    17  8
    8  8
    2  8
    13  8
    3  8
    
    5 3  
    13 11
    3 17
    15 20
    6 13
    17  9
    
    8 5   
     3  5
    17 16
     6  0
    17 10
     6 14
     3 19
     4 13
     0 17
    */
  • 相关阅读:
    【转】Java HotSpot(TM) 64-Bit Server VM warning: Insufficient space for shared memory file:
    kafka之partition分区及副本replica升级
    Rokid开发者社区skill之【历史上的今天】之简介+玩法+设计+实现+心得
    【转】批量删除redis中的key
    shell实现除法,保留小数点后N位
    [Django学习]中间件
    [Django学习]静态文件处理
    [Django学习]模板
    [Django学习]视图
    [Django学习]模型
  • 原文地址:https://www.cnblogs.com/tiberius/p/11257907.html
Copyright © 2011-2022 走看看