読者です 読者をやめる 読者になる 読者になる

土下座しながら探索中

主に競技プログラミング

AOJ 1086 : Live Schedule

問題リンク:Live Schedule | Aizu Online Judge

解法:
動的計画法

dp[何日目か][負担][連続してライブをした日数] := 最大利益 とする

遷移の状態としては、
・何もしない
・その場所だけでライブ
・連続してライブ
の3つがある

Eが0の時はそこでライブを行えない亊に注意
連続してライブを行う際に途中でEが0になったらbreakする亊を忘れないように

コード:

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29)
#define MAX 40

using namespace std;

int C,D,W,X;
int E[MAX][MAX];
int F[MAX][MAX];
int dp[40][60][10];//dp[D:day][W:burden][X:kurenai]

int main()
{
  while(scanf("%d %d %d %d",&C,&D,&W,&X),C|D|W|X)
    {  
      rep(i,C)rep(j,D)scanf("%d",&E[i][j]);
      rep(i,C)rep(j,D)scanf("%d",&F[i][j]);  

      rep(i,40)rep(j,60)rep(k,10)dp[i][j][k] = -inf;
      dp[0][0][0] = 0;

      rep(day,D)
	{
	  rep(burden,W+1)
	    {
	      rep(x,X+1)
		{
		  //何もしない
		  dp[day+1][burden][x] = max(dp[day+1][burden][x],
					     dp[day  ][burden][x]);

		  rep(region,C)
		    {
		      if(E[region][day] == 0)continue;
		      
		      //そこでラヴライヴ
		      if(burden + F[region][day] <= W)
			{
			  dp[day+1][burden+F[region][day]][x] = max(dp[day+1][burden+F[region][day]][x],
								    dp[day][burden][x]+E[region][day]);
			}

		      //ラブライブ!
		      int cost = 0;
		      int value = 0;
		      
		      for(int cur=region;cur>=0;cur--)
			{
			  cost  += F[cur][day];
			  value += E[cur][day];
			  if(cur == region)continue;
			  if(E[cur][day] == 0)break;
			  if(burden + cost <= W && x + 1 <= X)
			    {
			      dp[day+1][burden+cost][x+1] = max(dp[day+1][burden+cost][x+1],
								dp[day  ][burden     ][x  ]+value);
			    }
			  else break;
			}
		      
		      cost = 0;
		      value = 0;
		      for(int cur=region;cur<C;cur++)
			{
			  cost  += F[cur][day];
			  value += E[cur][day];
			  if(E[cur][day] == 0)break;
			  if(cur == region)continue;
			  if(burden + cost <= W && x + 1 <= X)
			    {
			      dp[day+1][burden+cost][x+1] = max(dp[day+1][burden+cost][x+1],
								dp[day  ][burden     ][x  ]+value);
			    }
			  else break;
			}
		      
		    }

		}
	    }
	}

      int ans = 0;
      rep(i,W+1)rep(j,X+1)
	{
	  ans = max(ans,
		    dp[D][i][j]);
	}
      printf("%d\n",ans);

    }
  return 0;
}