RUPC (Ritsumeikan University Programming Contest) 2011 Problem E Anipero
問題
イベントにいくつかのアーティストを招待する。
アーティストはシークレットアーティストn組と、通常のアーティスト組に分かれていて、
シークレットアーティストの候補の中から1組または2組を、
通常のアーティストの候補の中からx組以上を招待する必要がある。
それぞれのアーティストを招待するのにかかる費用および、アーティストを招待したときの満足度が与えられる。
費用の和がlimit以下で、かつ上の条件を満たすようなアーティストの選び方のうち、招待したアーティストの満足度の和が最大になるような選び方の、満足度の和を求めよ。
制約条件
n≦100
m≦100
x≦m
limit≦1000
それぞれの費用、満足度≦10
方針
動的計画法による。
まずは通常のアーティストをx組選ぶ選び方を求める。
dp[i][j]を、アーティストをi組選び、そのときの費用の和がjであるようなアーティストの選び方をしたときの、満足度の最大値とする。
この表をアーティストを昇順に、iを降順にまわすループにより更新することで、
dp[i][j]が求まる。
dp2[0][j]を、通常のアーティストをx人以上選び、費用がjかかっているときの満足度の最大値とする。
この表を同じようにシークレットアーティストについて更新することで、シークレットアーティストをi人招待した場合の、費用と満足度の表が得られる。
dp2[i][j]のなかで1≦i≦2かつj≦limitを満たす最大のdp2[i][j]が求める答えである。
int sw[100],sv[100],w[100],v[100]; int dp[103][1001],dp2[3][1001]; int main() { int limit,n,m,x; while(cin>>limit>>n>>m>>x,limit){ string tmp; rep(i,n)cin>>tmp>>sw[i]>>sv[i]; rep(i,m)cin>>tmp>>w[i]>>v[i]; memset(dp,-1,sizeof(dp)); memset(dp2,-1,sizeof(dp2)); dp[0][0]=0; rep(k,m)for(int i=m-1;i>=0;i--)rep(j,1001)if(dp[i][j]>=0){ if(j+w[k]<=limit)dp[i+1][j+w[k]]=max(dp[i+1][j+w[k]],dp[i][j]+v[k]); } for(int i=x;i<=m;i++)rep(j,1001)dp2[0][j]=max(dp2[0][j],dp[i][j]); int ans=-1; rep(k,n)for(int i=1;i>=0;i--)rep(j,1001)if(dp2[i][j]>=0){ if(j+sw[k]<=limit)dp2[i+1][j+sw[k]]=max(dp2[i+1][j+sw[k]],dp2[i][j]+sv[k]); } rep(i,2)rep(j,1001)ans=max(ans,dp2[i+1][j]); cout<<ans<<endl; } return 0; }