POJ 1185 炮兵陣地 dp三維和二維的區別 狀壓dp

參考:
https://www.cnblogs.com/scau20110726/archive/2013/02/27/2935256.html

二維的dp
最開始寫了的dp數組是二維的,想法也很簡單
dp[r][i]表示:第r行取i狀態的時候,i行以及以上的行一共有多少士兵

狀態轉移:

dp[r][i] = max(dp[r][i], dp[r-2][k] + cntSol[j]+ cntSol[i]);

cntSol[i] 表示第i個狀態有幾個士兵

但是一直wa,但是不明白開三維數組的作用。

這樣的寫法,可以保證第r行和前兩行的不衝突,但是在對i行的狀態的進行變化的時候,會影響r-1行的狀態,進而影響r-2行的狀態,這個時候dp[r-2][k]應該隨着j的變化而變化的,也就是說r行的計算會影響子問題的最優解,不滿足動態規劃的最優子結構

也就說我們在考慮第r行的時候,取了dp[r-2][k] + cntSol[j]+ cntSol[i]裏面的j、k組合裏面的最大值,把dp[r-2][k]當做一個定值來計算,但其實這個值會隨着r-1行的變化而變化


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <string>

using namespace std;

#define debug(x) cout<<#x<<": "<<x<<endl;

char tempG[11];
int bitG[101];
int cntSol[101];
int sol[70];
int maxSol = 0;
int dp[101][70];

int N,M;

int cnt1(int a){
    int ret = 0;
    while( a>0 ){
        ret++;
        a&=(a-1);
    }
    return ret;
}

int findw(){
    int ret = 0;
    for(int i = 0; i<(1<<M);i++){
        if( i&(i<<1) || i&(i<<2) ){
            continue;
        }
        sol[maxSol] = i;
        cntSol[maxSol] = cnt1(i);
        maxSol++;
    }

    if( N>0 ){

        for(int i=0;i<maxSol;i++){

            if( bitG[0]&sol[i] )continue;

            dp[0][i] = cntSol[i];
            ret = max(ret,dp[0][i]);
        }
    }

    if(N>1){
        for(int i=0;i<maxSol;i++){
            for(int j=0;j<maxSol;j++){
                if( bitG[0]&sol[j] )continue;
                if( bitG[1]&sol[i] ) continue;
                if( sol[i]&sol[j] ) continue;
                dp[1][i] = max(dp[1][i], dp[0][j] + cntSol[i]);
                ret = max(ret,dp[1][i]);
            }
        }
    }

    for(int r = 2; r < N; r ++){
        for(int i=0;i<maxSol;i++){

            if(bitG[r]&sol[i])continue;

            for(int j = 0;j < maxSol;j ++){

                if(bitG[r-1]&sol[j])continue;
                if(sol[i]&sol[j])continue;

                for(int k = 0;k < maxSol;k ++){

                    if(bitG[r-2]&sol[k])continue;

                    if(sol[i]&sol[k])continue;
                    if(sol[k]&sol[j])continue;

                    //dp[r][i]= max (dp[r][i], dp[r-1][j]+dp[r-2][k]) + cntSol[i];

                    dp[r][i] = max(dp[r][i], dp[r-2][k] + cntSol[j]+ cntSol[i]);

                    //dp[r][i] = max(dp[r][i], dp[r-1][j] + cntSol[i]);

                    ret = max(ret,dp[r][i]);
                }
            }
        }
    }
    return ret;
}

**CODE**
int main()
{

    while(scanf("%d%d",&N,&M) != EOF){
        //scanf("%d%d",&N,&M);
        memset(bitG,0,sizeof(bitG));
        memset(dp,0,sizeof(dp));
        memset(cntSol,0,sizeof(cntSol));
        maxSol = 0;

        for(int i=0;i<N;i++){
            scanf("%s",tempG);
            for(int j=0;j<M;j++){
                if( tempG[j]=='H' ){
                    bitG[i] += (1<<j);
                }
            }
        }

        int ret = findw();
        //disp();

        printf("%d\n",ret);
    }
    return 0;
}

/*
5 4
HHHH
HHHH
HHHH
HHHH
HHHH

5 4
PHHH
HHHP
HHHH
PHHH
HHHP

5 4
PPPP
PPPP
PPPP
PPPP
PPPP

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

1 4
PPPP

0 0

1 10
PPPPPPPPPP

2 10
PPPPPPPPPP
PPPPPPPPPP

8 10
PPPPPPPPPP
PPPPPPPPPP
PPPPPPPPPP
PPPPPPPPPP
PPPPPPPPPP
PPPPPPPPPP
PPPPPPPPPP
PPPPPPPPPP

*/


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <string>

using namespace std;

#define debug(x) cout<<#x<<": "<<x<<endl;

char tempG[11];
int bitG[101];
int cntSol[101];
int sol[70];
int maxSol = 0;
int dp[101][70][70];

int N,M;

int cnt1(int a){
    int ret = 0;
    while( a>0 ){
        ret++;
        a&=(a-1);
    }
    return ret;
}


int findw(){
    int ret = 0;
    for(int i = 0; i<(1<<M);i++){
        if( i&(i<<1) || i&(i<<2) ){
            continue;
        }
        sol[maxSol] = i;
        cntSol[maxSol] = cnt1(i);
        maxSol++;
    }
    
    if( N>0 ){
            
        for(int i=0;i<maxSol;i++){
                
            if( bitG[0]&sol[i] )continue;

            dp[0][i][0] = cntSol[i];
            ret = max(ret,dp[0][i][0]);
        }
    }

    if(N>1){
        for(int i=0;i<maxSol;i++){
            for(int j=0;j<maxSol;j++){
                if( bitG[0]&sol[j] )continue;
                if( bitG[1]&sol[i] ) continue;
                if( sol[i]&sol[j] ) continue;
                dp[1][i][j] = max(dp[1][i][j], dp[0][j][0] + cntSol[i]);
                ret = max(ret,dp[1][i][j]);
            }
        }
    }

    for(int row = 2;row < N; row ++){
        for(int i=0;i<maxSol;i++){

            if(bitG[row]&sol[i])continue;

            for(int j = 0;j < maxSol;j ++){

                if(bitG[row-1]&sol[j])continue;
                if(sol[i]&sol[j])continue;

                for(int k = 0;k < maxSol;k ++){

                    if(bitG[row-2]&sol[k])continue;

                    if(sol[i]&sol[k])continue;
                    if(sol[k]&sol[j])continue;

                    dp[row][i][j] = max(dp[row][i][j], dp[row-1][j][k] + cntSol[i]);

                    ret = max(ret,dp[row][i][j]);
                }
            }
        }
    }
    return ret;
}


int main()
{

    while(scanf("%d%d",&N,&M) != EOF){
        //scanf("%d%d",&N,&M);
        memset(bitG,0,sizeof(bitG));
        memset(dp,0,sizeof(dp));
        memset(cntSol,0,sizeof(cntSol));
        maxSol = 0;

        for(int i=0;i<N;i++){
            scanf("%s",tempG);
            for(int j=0;j<M;j++){
                if( tempG[j]=='H' ){
                    bitG[i] += (1<<j);
                }
            }
        }

        int ret = findw();
        //disp();

        printf("%d\n",ret);
    }
    return 0;
}
/*
5 4
HHHH
HHHH
HHHH
HHHH
HHHH

5 4
PHHH
HHHP
HHHH
PHHH
HHHP

5 4
PPPP
PPPP
PPPP
PPPP
PPPP

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

1 4
PPPP

0 0

1 10
PPPPPPPPPP

2 10
PPPPPPPPPP
PPPPPPPPPP

6 10
PPPPPPPPPP
PPPPPPPPPP
PPPPPPPPPP
PPPPPPPPPP
PPPPPPPPPP
PPPPPPPPPP

*/

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章