1. 程式人生 > >【POJ1015】Jury compromise 多個費用的背包

【POJ1015】Jury compromise 多個費用的背包

ise best parse || inline memory 最大 tor 題目

這是一道比較綜合的動態規劃問題。
首先,根據題目中的從N個人中選出M個人,並且要使得某個目標函數最優,可以想到是背包問題,且因為要取出M個人,人數也應該作為背包體積的一個維度。
其次,要求輸出路徑,因此不能進行滾動數組優化(優化後無法記錄狀態轉移途徑)。
再次觀察要求最優的函數,是一個相減取絕對值的函數,因此,可能出現負數,因此要給零點加一個偏移量。
狀態的選取:\(dp[i][j][k]\)表示前 i (階段)個物品中選取 j 個,且目標函數值為 k 時,和函數的最大值是多少。

代碼如下:

#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#define cls(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=201;
const int maxm=21;
const int maxdiff=801;

int n,m,kase,d[maxn],p[maxn],mid,ans_p,ans_d;
int dp[maxn][maxm][maxdiff],path[maxn][maxm][maxdiff];
std::vector<int> v;

void init(){
    cls(dp,0xcf);cls(path,0);
    v.clear();
    ans_p=ans_d=0;
}

void read_and_parse(){
    mid=m*20;//偏移量選取
    for(int i=1;i<=n;i++)
        scanf("%d%d",&p[i],&d[i]);
    for(int i=0;i<=n;i++)
        dp[i][0][mid]=0;
}

void print(int i,int j,int k){//路徑處理
    if(!j)return;
    int idx=path[i][j][k];
    print(idx-1,j-1,k-(p[idx]-d[idx]));
    ans_d+=d[idx],ans_p+=p[idx];
    v.push_back(idx);
}

void solve(){
    for(int i=1;i<=n;i++){
        int cost=p[i]-d[i],val=p[i]+d[i];
        for(int j=1;j<=m;j++)
            for(int k=0;k<=mid<<1;k++){
                dp[i][j][k]=dp[i-1][j][k];
                path[i][j][k]=path[i-1][j][k];
                if(k-cost>=0&&dp[i][j][k]<dp[i-1][j-1][k-cost]+val){
                    dp[i][j][k]=dp[i-1][j-1][k-cost]+val;
                    path[i][j][k]=i;
                }
            }
    }
    int i,idx;
    for(i=0;i<=mid;i++)
        if(dp[n][m][mid-i]>=0||dp[n][m][mid+i]>=0)
            break;
    idx=(dp[n][m][mid-i]>dp[n][m][mid+i])?mid-i:mid+i;//比較和函數的大小

    print(n,m,idx);
    printf("Jury #%d\n", ++kase);
    printf("Best jury has value %d for prosecution and value %d for defence:\n",ans_p,ans_d);
    for(i=0;i<v.size();i++)printf(" %d",v[i]);
    puts("\n");
}

int main(){
    while(scanf("%d%d",&n,&m)&&m+n){
        init();
        read_and_parse();
        solve();
    }
    return 0;
}

【POJ1015】Jury compromise 多個費用的背包