程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> poj1185 炮兵陣地(狀態壓縮)

poj1185 炮兵陣地(狀態壓縮)

編輯:C++入門知識

炮兵陣地
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 15261   Accepted: 5743

Description

司令部的將軍們打算在N*M的網格地圖上部署他們的炮兵部隊。一個N*M的地圖由N行M列組成,地圖的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下圖。在每一格平原地形上最多可以布置一支炮兵部隊(山地上不能夠部署炮兵部隊);一支炮兵部隊在地圖上的攻擊范圍如圖中黑色區域所示:

 

如果在地圖中的灰色所標識的平原上部署一支炮兵部隊,則圖中的黑色的網格表示它能夠攻擊到的區域:沿橫向左右各兩格,沿縱向上下各兩格。圖上其它白色網格均攻擊不到。從圖上可見炮兵的攻擊范圍不受地形的影響。
現在,將軍們規劃如何部署炮兵部隊,在防止誤傷的前提下(保證任何兩支炮兵部隊之間不能互相攻擊,即任何一支炮兵部隊都不在其他支炮兵部隊的攻擊范圍內),在整個地圖區域內最多能夠擺放多少我軍的炮兵部隊。

Input

第一行包含兩個由空格分割開的正整數,分別表示N和M;
接下來的N行,每一行含有連續的M個字符('P'或者'H'),中間沒有空格。按順序表示地圖中每一行的數據。N <= 100;M <= 10。
Output

僅一行,包含一個整數K,表示最多能擺放的炮兵部隊的數量。
Sample Input

5 4
PHPP
PPHH
PPPP
PHPP
PHHPSample Output

6Source

Noi 01
自己寫的一個狀態壓縮,比較激動啊,不過我寫的比別人寫的運行時間要長,希望哪位大神看了可以給個建議
Memory: 1872 KBTime: 422 MSLanguage: CResult: Accepted

<SPAN style="FONT-FAMILY: Times New Roman">#include<stdio.h>  
  
struct recor{  
    int r[65],num,s[65];  
}a[110];//a[i]保存i行的所有滿足水平不重疊要求的狀態   
int dp[110][65][65],tem,n,m;  
  
int max(int i,int j)  
{  
    return i>j?i:j;  
}  
void pb(int i)  
{  
    int j,x,d;  
    for(j=0;j<1<<m;j++)  
    {  
        if(!(j&tem))</SPAN><SPAN style="FONT-FAMILY: 'Times New Roman'">//</SPAN><SPAN style="FONT-FAMILY: 'Times New Roman'">①若是1表示平原0表示高山,這一步便無法找出滿足條件的狀態,新手請手動模擬一下位運算來體會這句話的含義</SPAN><SPAN style="FONT-FAMILY: Times New Roman">   
        {  
            if((j&(j<<1))||(j&(j<<2)))//這是排除一行大炮可以攻擊到對方的情況,位運算時一定要注意位運算的優先級,加括號</SPAN><SPAN style="FONT-FAMILY: 'Times New Roman'">   
                continue;  
        a[i].r[a[i].num]=j;//保存下一行中滿足題意的狀態   
        d=j;  
        x=d%2;  
        while(d=(d>>1))  
        {  
            x+=d%2;  
        }  
        a[i].s[a[i].num++]=x;//x表示的是每一個狀態對應的炮數   
        }  
    }  
}  
int main()  
{  
    int i,j,sum,k,p,max;  
    char c;  
    while(scanf("%d%d",&n,&m)!=EOF)  
    {  
    for(i=0;i<n;i++)  
    {  
        a[i].num=0;  
        tem=0;  
        getchar();  
        for(j=0;j<m;j++)  
        {  
            c=getchar();  
            if(c=='P')  
                tem=(tem<<1);  
            else tem=(tem<<1)+1;//這個就是把這個圖轉化成二進制tem,0表示平原,1表示高山,我開始不理解為什麼不把平原設成1,那樣1表示可以0表示不可以豈不是更符合我們平常的思維?但是等我那樣寫了我才發現問題,請見標號①   
        }  
        pb(i);  
    }  
    for(i=1;i<n;i++)  
        for(j=0;j<a[i].num;j++)  
            for(p=0;p<a[i-1].num;p++)  
                dp[i][j][p]=0;//初始化   
    for(j=0;j<a[0].num;j++)  
        for(p=0;p<a[0].num;p++)  
            dp[0][j][p]=a[0].s[j];//同樣也是初始化   
    for(j=0;j<a[1].num;j++)//因為前兩行有點特殊,所以單獨處理了   
        for(p=0;p<a[0].num;p++)  
            if(!(a[1].r[j]&a[0].r[p]))  
                dp[1][j][p]=dp[0][p][0]+a[1].s[j];  
    for(i=2;i<n;i++)//每一行   
    {  
        for(p=0;p<a[i].num;p++)//每一行的所有狀態   
        {  
            max=0;  
            for(k=0;k<a[i-1].num;k++)//前一行的狀態   
            {  
                for(j=0;j<a[i-2].num;j++)//前兩行的狀態   
                {  
                    if((!(a[i-1].r[k]&a[i-2].r[j]))&&(!(a[i].r[p]&a[i-2].r[j]))&&(!(a[i].r[p]&a[i-1].r[k])))//三行的判斷前後是否有重疊的情況   
                    {  
                        if(dp[i][p][k]<dp[i-1][k][j]+a[i].s[p])  
                            dp[i][p][k]=dp[i-1][k][j]+a[i].s[p];//這就是取最大值了   
                    }  
                }  
            }  
        }  
    }  
    max=0;  
    if(n>1)//好像不用分情況,寫麻煩了,n=1時n-1就是0啊   
    for(i=0;i<a[n-1].num;i++)  
        for(j=0;j<a[n-2].num;j++)  
        {     
            if(max<dp[n-1][i][j])  
                max=dp[n-1][i][j];  
        }  
        else  
            for(j=0;j<a[0].num;j++)  
            {  
                if(max<dp[0][j][0])  
                max=dp[0][j][0];  
            }  
        printf("%d\n",max);  
    }  
    return 0;  
}</SPAN>  

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved