AOJ2285 Anipero
問題リンク Anipero
- 解法
DPです。dp表をシークレット用とスタンダード用の2つ用意します。
dp[i][x][L]: i番目までのアイドルに対して、費用Lを使ってx人雇う時の最大満足度
とすれば解けます。
この表を2つ作ったら、費用L (L <= LIMIT)だけ使ってスタンダードアイドルをx人( X <= x )雇うとした時、得られる満足度は
dp_standard[M-1][x][L] + max( dp_secret[N-1][1][LIMIT-L], dp_secret[N-1][2][LIMIT-L])
と求まります。あとは、これを最大化するL, xの組み合わせを見つけるだけです。
- ソース
import java.util.Scanner; //Anipero public class AOJ2285 { void run(){ Scanner sc = new Scanner(System.in); for(;;){ int L = sc.nextInt(), n = sc.nextInt(), m = sc.nextInt(), X = sc.nextInt(); if((L|n|m|X)==0)break; int[] e1 = new int[n], s1 = new int[n]; for(int i=0;i<n;i++){ sc.next(); e1[i] = sc.nextInt(); s1[i] = sc.nextInt(); } int[] e2 = new int[m], s2 = new int[m]; for(int i=0;i<m;i++){ sc.next(); e2[i] = sc.nextInt(); s2[i] = sc.nextInt(); } int[][][] dp1 = new int[n][3][L+1]; //-1: 実現不可能のマーク for(int i=0;i<n;i++)for(int x=1;x<=2;x++)for(int l=0;l<=L;l++)dp1[i][x][l] = -1; for(int l=e1[0];l<=L;l++)dp1[0][1][l] = s1[0]; for(int i=1;i<n;i++)for(int x=1;x<=2;x++)for(int l=0;l<=L;l++){ int max = -1; if(l>0)max = dp1[i][x][l-1]; if(l-e1[i]<0){ max = Math.max(max, dp1[i-1][x][l]); } else { if(dp1[i-1][x][l]>=0)max = Math.max(max, dp1[i-1][x][l]); if(dp1[i-1][x-1][l-e1[i]]>=0)max = Math.max(max, dp1[i-1][x-1][l-e1[i]]+s1[i]); } dp1[i][x][l] = max; } int[][][] dp2 = new int[m][m+1][L+1]; for(int i=0;i<m;i++)for(int x=1;x<=m;x++)for(int l=0;l<=L;l++)dp2[i][x][l] = -1; for(int l=e2[0];l<=L;l++)dp2[0][1][l] = s2[0]; for(int i=1;i<m;i++)for(int x=1;x<=m;x++)for(int l=0;l<=L;l++){ int max = -1; if(l>0)max = dp2[i][x][l-1]; if(l-e2[i]<0){ max = Math.max(max, dp2[i-1][x][l]); } else { if(dp2[i-1][x][l]>=0)max = Math.max(max, dp2[i-1][x][l]); if(dp2[i-1][x-1][l-e2[i]]>=0)max = Math.max(max, dp2[i-1][x-1][l-e2[i]]+s2[i]); } dp2[i][x][l] = max; } int max = 0; for(int x=X;x<=m;x++)for(int l=0;l<=L;l++){ if(dp2[m-1][x][l]==-1)continue; if(dp1[n-1][1][L-l]==-1&&dp1[n-1][2][L-l]==-1)continue; int v = dp2[m-1][x][l] + Math.max(dp1[n-1][1][L-l], dp1[n-1][2][L-l]); max = Math.max(max, v); } System.out.println(max); } } public static void main(String[] args) { new AOJ2285().run(); } }