AOJ0263 Beat Panel

問題リンク Beat Panel

  • 解法

DPで解きました。
dp[i][S]: iターン目終了時点のボタンの状態がSのときの最高得点
という表を埋めます。
ボタンの状態や押すボタンの状態、押した後のボタンの状態など全部ビット操作で書けば、コードがめっさスッキリしますね。

  • ソース
import java.util.Arrays;
import java.util.Scanner;

//Beat Panel
public class AOJ0263 {

	void run(){
		Scanner sc = new Scanner(System.in);
		int[][] dp = new int[2][1<<16];
		for(;;){
			int n = sc.nextInt(), c = sc.nextInt();
			if(n+c==0)break;
			int[] a = new int[n], b = new int[c];
			for(int i=0;i<n;i++)for(int j=0;j<16;j++)a[i] = (a[i]<<1) + sc.nextInt();
			for(int i=0;i<c;i++)for(int j=0;j<16;j++)b[i] = (b[i]<<1) + sc.nextInt();
			Arrays.fill(dp[0], -1);
			dp[0][0] = 0;
			int X = 1;
			for(int i=0;i<n;i++,X=1-X){
				Arrays.fill(dp[X], -1);
				for(int S=0;S<1<<16;S++)if(dp[1-X][S]!=-1){
					int light = S|a[i];
					for(int j=0;j<c;j++){
						int pushed = light & b[j];
						int point = Integer.bitCount(pushed);
						int nx = light & ~pushed;
						dp[X][nx] = Math.max(dp[X][nx], dp[1-X][S] + point);
					}
				}
			}
			int res = 0;
			for(int S=0;S<1<<16;S++)res = Math.max(res, dp[1-X][S]);
			System.out.println(res);
		}
	}
	
	public static void main(String[] args) {
		new AOJ0263().run();
	}
}