Poj 1185 java实现--状态压缩

这个题目和之前做过的Corn Fields,可以说一模一样.....关于状态压缩的动态规划。

Corn Fields说的时不能上下左右相邻,这个变成不能上下左右2个跨度的相邻。

所以基本思路相同:

1.压缩行的状态,将每行的可以选择的情况视为二进制,进而转为十进制去执行判断

2.记录每行的状态,进行比较。因为不能和上一行和上上一行相邻,所以仍旧使用[(状态1&状态2) == 0]来判断当前行是否合法。

3.Corn Fields只需要和上一行进行判断,所以可以枚举每种状态,直接讨论当前行能否放置,当前状态是否符合1不相邻。二维数组开辟dp[行][1<<列]大小也不会很多,但是本题目需要和前两行判断,所以数组变成三维

dp[行][1<<列][1<<列],直接记录会比较大。这里先对每行所有状态进行一次过滤,取出符合  相邻两位,相邻三位没有相同的1的情况,使用索引标记情况,数组值为当前情况对应的状态。最后可以算出符合基本情况的状态只有60多中,所以三维数组可以开辟为dp[行][70][70]大小。

4.执行比较操作,排除不符合情况的状态,这个和Cron Fields相同。

a.当前行放置是否符合地形规则

b.当前行放置是否和上一行不相邻

c.当前行放置是否和上上一行不相邻

5.统计最后一行的结果即可。

dp数组的含义:

在第三步中,使用了一个数组,就叫做possibleStatus[]吧,记录了所有的可能状态。

dp[i][j][k]代表在第i行,并且当前行状态为possibleStatus[k],并且上一行状态为possibleStatus[j]的情况下,可以放置炮兵的最大数量。

所以状态转移方程:

i--行,j--当前行possibleStatus状态的索引,p--上一行possibleStatus状态的索引,k--上上一行能够放置的possibleStatus状态的索引。

所以

当前行的状态:dp[i][p][k]

上一行的状态:dp[i-1][k][p]

dp[i][p][j] = Math.max(dp[i][p][j],dp[i-1][k][p]+oneNumCnt(possibleStatus[j]))

oneNumCnt(possibleStatus[j])就是当前放置状态possibleStatus[j]中可放炮兵的数量---就是1的数量。

java代码如下:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
    static char[][] info;
    static int[][] transInfo;
    static int[] possibleStatus;
    static int possibleStatusCnt;
    static int[][][] dp;
    static int[] rowInitPosition;

    static int n,m;

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());

        info = new char[n][m];
        transInfo = new int[n][m];
        possibleStatus = new int[100];
        dp = new int[n][100][100];
        rowInitPosition = new int[n];

        initDp();
        initPossibleStatus();

        char[] inputCharArray;
        for(int i = 0;i<info.length;i++){
            inputCharArray = br.readLine().toCharArray();
            info[i] = inputCharArray;
            for(int j = 0;j<info[0].length;j++){
                transInfo[i][j] = inputCharArray[j] == 'P'?1:0;
                rowInitPosition[i] += transInfo[i][j]*(1<<(info[0].length-1-j));
            }
        }

        for(int i = 0;i<possibleStatusCnt;i++){
            if((possibleStatus[i]&rowInitPosition[0]) != possibleStatus[i]){
                continue;
            }
            dp[0][0][i] = getNumberBinaryOneCnt(possibleStatus[i]);
        }

        for(int i=1;i<n;i++){
            for(int j = 0;j<possibleStatusCnt;j++){
                //current row
                if((possibleStatus[j]&rowInitPosition[i]) != possibleStatus[j]){
                    continue;
                }
                for(int k = 0;k<possibleStatusCnt;k++){
                //current-1 row
                    if(is2RowPositionNotOk(possibleStatus[j], possibleStatus[k])){
                        continue;
                    }
                    for(int p = 0;p<possibleStatusCnt;p++){
                        //current-2 row
                        if(is2RowPositionNotOk(possibleStatus[j], possibleStatus[p])){
                            continue;
                        }
                        if(dp[i-1][k][p] == -1){
                            continue;
                        }
                        dp[i][p][j] = Math.max(dp[i][p][j],dp[i-1][k][p]+getNumberBinaryOneCnt(possibleStatus[j]));
                    }
                }
            }
        }

        int result = 0;
        for(int i = 0;i<n;i++){
            for(int j = 0;j<possibleStatusCnt;j++){
                for(int k = 0;k<possibleStatusCnt;k++){
                    result = Math.max(result,dp[i][j][k]);
                }
            }
        }
        System.out.println(result);
    }

    private static void initPossibleStatus(){
        possibleStatusCnt = 0;
        for(int i = 0;i<(1<<m);i++){
            if((i&(i<<1)) == 0 && (i&(i<<2)) == 0){
                possibleStatus[possibleStatusCnt] = i;
                possibleStatusCnt++;
            }
        }
    }

    private static void initDp(){
        for (int[][] ints : dp) {
            for (int[] anInt : ints) {
                Arrays.fill(anInt, -1);
            }
        }
    }

    private static boolean is2RowPositionNotOk(int x, int y){
        return (x & y) != 0;
    }

    private static int getNumberBinaryOneCnt(int num){
        int cnt = 0;
        while (num != 0){
            num = (num&(num-1));
            cnt++;
        }
        return cnt;
    }
}

posted @ 2021-04-30 17:20  Monstro  阅读(139)  评论(0)    收藏  举报