问题
https://vjudge.net/problem/UVA-12260
分析
这道题的核心在于由于P采用贪婪的方法,所以它一定在前i个中至少占到一半左右的数量,所以d[i][j].value代表在J在前i个物品中占有了j个时候的最大价值,j<=(i+1)/2,然后dp[i][j].loss代表了对于P的总价值造成的损失,设n个P的value之和为sum,P每次选择,都会对sum造成损失,如果损失最小,那么P的最终收益就会最大
状态转移过程有点类似于背包问题,每次都是选择或者不选最后一个物品
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=1000+5;
struct Googy{
int v1,v2;
Googy(int v1=0,int v2=0):v1(v1),v2(v2){}
bool operator < (const Googy &rhs) const {
return v1>rhs.v1 || (v1==rhs.v1 && v2<rhs.v2);
}
};
int n,kase=0,first,tot;
Googy goody[maxn];
char s[20];
pair<int,int> dp[maxn][maxn];
int main(void){
scanf("%d",&kase);
while(kase--){
scanf("%d%s",&n,s);
// tot=0;
for(int i=1;i<=n;++i){
scanf("%d%d",&goody[i].v1,&goody[i].v2);
// tot+=goody[i].v1;
}
sort(goody+1,goody+1+n);
if(s[0]=='P') {
dp[1][0]=make_pair(0,goody[1].v1);
first=2;
}else{
first=1;
}
for(int i=first;i<=n;++i){
int lim=(i-first+2)>>1;
dp[i][0]=make_pair(dp[i-1][0].first,dp[i-1][0].second+goody[i].v1);
for(int j=1;j<lim;++j){
dp[i][j]=max(make_pair(dp[i-1][j].first,dp[i-1][j].second+goody[i].v1),
make_pair(dp[i-1][j-1].first+goody[i].v2,dp[i-1][j-1].second));
}
if(lim==((i-1-first+2)>>1)){
dp[i][lim]=max(make_pair(dp[i-1][lim].first,dp[i-1][lim].second+goody[i].v1),
make_pair(dp[i-1][lim-1].first+goody[i].v2,dp[i-1][lim-1].second));
}else{
dp[i][lim]= make_pair(dp[i-1][lim-1].first+goody[i].v2,dp[i-1][lim-1].second);
}
}
printf("%d %d\n",dp[n][(n-first+2)>>1].second,dp[n][(n-first+2)>>1].first);
}
return 0;
}