AOJ 2221 KULASIS
方針
i行目のスイッチは、時間割のi-1行目より前に対しては影響を与えない。
よって、dp[i][j]にi行目のスイッチを状態jにしたときの、
時間割のi行目までのスコアの最大値を持つようなDPができる。
ソースコード
int score[]={0,0,60,70,80}; int tb[5][5], dp[4][1<<2*4]; int main() { int n; scanf("%d",&n); rep(i,n) { rep(i,5)rep(j,5)scanf("%d",tb[i]+j); rep(i,4)rep(j,1<<2*4)dp[i][j]=0; rep(i,1<<2*4){ dp[0][i]=0; rep(j,5)if(tb[0][j]){ int sc=tb[0][j]; if(j>0)sc+=i>>2*j-2&3; if(j<4)sc+=i>>2*j&3; while(sc>4)sc-=4; dp[0][i]+=score[sc]; } } for(int i=1;i<4;i++)rep(j,1<<2*4)rep(jj,1<<2*4){ int sum=dp[i-1][j]; rep(k,5)if(tb[i][k]){ int sc=tb[i][k]; if(k>0)sc+=(j>>2*k-2&3) + (jj>>2*k-2&3); if(k<4)sc+=(j>>2*k&3) + (jj>>2*k&3); while(sc>4)sc-=4; sum+=score[sc]; } dp[i][jj]=max(dp[i][jj],sum); } int ans=0; rep(i,1<<2*4){ int sum=dp[3][i]; rep(j,5)if(tb[4][j]){ int sc=tb[4][j]; if(j>0)sc+=i>>2*j-2&3; if(j<4)sc+=i>>2*j&3; while(sc>4)sc-=4; sum+=score[sc]; } ans=max(ans,sum); } cout<<ans<<endl; } return 0; }