中文题,题意不再赘述。
解法:从题目可以知道,每一行的状态只与前两行有关。已知N < 100, M <= 10。很明显的可以把M压缩,把M中的每一个位置的状态可以用0,1表示。所以M的总状态可以用长度为M的二进制转化成的十进制数表示。计算可以发现总的合法状态并不多,因为要保证同一行的两个士兵不能相互攻击到。
求合法状态的关键代码:
REP(i, (1<<m)) { p = i; if(((p << 1) & i) || ((p << 2) & i)) continue; num[sum] = 0; while(p) {num[sum] += (p&1); p >>= 1;} status[sum++] = i; }
status[p] = i表示表示第p个合法的状态是i。num[i] = a,表示状态为i 时安放a个炮兵。
这些数据都处理出来以后在预处理一下当前棋盘的状态0表示P,1表示H。chess[i] = s表示第i行的状态为s。
设dp[i][j][k]表示第i行的状态为j,第i - 1行的状态为k。
dp[i][j][k] = max(dp[i-1][k][p]) + num[j];
满足 (status[j]& status[k]) == 0
((status[j] & chess[i]) == 0 && (status[k] & chess[i-1]) == 0)
((status[k] & status[p]) == 0 && (status[j] & status[p]) == 0)
对于dp[0][j][k]初始化时单独些出来。dp[0][j][k] = num[j]; (不跟原棋盘冲突的情况下)
ps: 状压dp,又是一个神级专题,等刷完poj训练计划一定好好搞搞!明天开始埋头猛刷poj,加油!!