【dp】POJ 1015 Jury Compromise
/*
基礎dp
K - Jury Compromise
題意: n組D[j],P[j]數字,選擇m組使選擇的D[j]和與P[j]和差最小,如果和差相等,選擇D[j]和與P[j]和的總和最大的。
題解:感覺自己菜到懷疑人生。。。
dp[i][j] 代表選第i個,選擇的D[]和與P[]和差為j的 最大總和。
path[i][j] 記錄前i個選擇的組。
ca[i] = D[i]-P[i];
he[i] = D[i]+P[i];
如果選擇的前i組和差無法達到j,那麼dp[i][j] = -1;
if(k 前面有路徑 && k 在前面的路徑上沒有出現)
dp[i][j+ca[k]] = max(dp[i][j+ca[k]],dp[i-1][j]+he[k]);
j 的原有範圍應該是-20*m~20*m , 將其範圍加上20*m 變成 0~40*m;
*/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1010;
int dp[21][N],path[21][N],res[N];
int a[210],b[210],ca[210],he[210];
int n;
int main()
{
int n,m,cas = 1;
while(cin >> n >> m)
{
if(!n && !m)
break;
for(int i = 0; i < n; i++)
{
cin >> a[i] >> b[i];
ca[i] = a[i]-b[i];
he[i] = a[i]+b[i];
}
memset(dp,-1,sizeof(dp));
memset(path,-1,sizeof(path));
dp[0][20*m] = 0;
for(int i = 0; i < m; i++)
{
for(int j = 0; j <= 40*m; j++)
{
if(dp[i][j] >= 0)
{
for(int k = 0; k < n; k++)
{
int flag = 0;
int pre = path[i][j];
int ans = j;
if(pre == k)
continue;
for(int f = i-1; f >= 1; f--)
{
ans -= ca[pre];
pre = path[f][ans];
if(pre == k)
{
flag = 1;
break;
}
}
if(!flag)
{
if(dp[i+1][j+ca[k]] < dp[i][j]+he[k])
{
dp[i+1][j+ca[k]] = dp[i][j]+he[k];
path[i+1][j+ca[k]] = k;
}
}
}
}
}
// for(int j = 0; j <= 40*m; j++)
// printf("%d %d %d\n",j,path[i+1][j],dp[i+1][j]);
// printf("\n");
}
int mx = 0,id = 0;
for(int i = 0; i <= 20*m; i++)
{
if(dp[m][20*m+i] > mx)
{
mx = dp[m][20*m+i];
id = i;
}
if(dp[m][20*m-i] > mx)
{
mx = dp[m][20*m-i];
id = -i;
}
if(dp[m][20*m+i] != -1 || dp[m][20*m-i] != -1)
break;
}
int ans = id+20*m;
int pre = path[m][ans];
//printf("%d\n",pre);
int ans1 = 0,ans2 = 0;
int k = m;
res[--k] = pre;
ans1 += a[pre];
ans2 += b[pre];
for(int i = m-1; i > 0; i--)
{
ans -= ca[pre];
pre = path[i][ans];
res[--k] = pre;
ans1 += a[pre];
ans2 += b[pre];
//printf("%d\n",pre);
}
sort(res,res+m);
//printf("%d %d\n",id,mx);
printf("Jury #%d\n",cas++);
printf("Best jury has value %d for prosecution and value %d for defence:\n",ans1,ans2);
printf("%d",res[0]+1);
for(int i = 1; i < m; i++)
printf(" %d",res[i]+1);
puts("");
}
return 0;
}
相關文章
- POJ1745Divisibility(dp)
- POJ2955 Brackets (區間DP)Racket
- POJ 2486 Apple Tree(樹形dp)APP
- POJ 1925 Spiderman(線性dp)IDE
- POJ 3744 概率dp+矩陣矩陣
- POJ1160 Post Office[序列DP]
- POJ 3249-Test for Job(拓撲排序&&DP)排序
- POJ 3107 Godfather(樹形dp)Go
- POJ 3017 單調佇列dp佇列
- POJ 3691 DNA repair (AC自動機 + dp)AI
- 【樹形dp】poj 1947 Rebuilding RoadsRebuild
- poj 1180 dp的斜率優化優化
- POJ 1664 放蘋果 (基礎組合dp)蘋果
- POJ 2955-Brackets(括號匹配-區間DP)Racket
- POJ 1276-Cash Machine(多重部分和-dp)Mac
- poj3017 dp+單調佇列佇列
- POJ2184 Cow Exhibition[DP 狀態負值]
- POJ 3254 Corn Fields:網格密鋪類 狀壓dp
- POJ 1141 Brackets Sequence(記錄路徑的dp)Racket
- 「暑期訓練」「基礎DP」 Common Subsequence (POJ-1458)
- POJ3107Godfather[樹形DP 樹的重心]Go
- POJ 1947 Rebuilding Roads(基礎的樹形dp)Rebuild
- POJ3744 Scout YYF I (概率DP + 矩陣優化)矩陣優化
- POJ 2411 Mondriaan's Dream:網格密鋪類 狀壓dp
- POJ1141 ZOJ1463 Brackets Sequence【區間dp】Racket
- POJ 3373 Changing Digits(記錄路徑的dp)Git
- POJ 3034 Whac-a-Mole(三維dp+處理小技巧)
- 演算法學習之路|POJ-2479最大子串和(簡單dp)演算法
- dp 套 dp(dp of dp)小記
- poj1179 區間dp(記憶化搜尋寫法)有巨坑!
- PAT-B 1015 德才論【排序】排序
- DP套DP
- POJ1849Two[DP|樹的直徑](擴充套件HDU4003待辦)套件
- [DP] 數位DP
- dp套dp 隨寫
- hihocoder 1015 KMP演算法 (KMP模板)KMP演算法
- 【DP】區間DP入門
- [DP] DP最佳化總結