Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 10789 | Accepted: 3878 |
Description
Input
Output
Sample Input
5 4 PHPP PPHH PPPP PHPP PHHP
Sample Output
6
分析:
第i行的放置情况仅与i-1和i-2行有关,与i-2之前行的放置状态无关,且每次分析第i行的放置过程一样,满足动态规划算法的条件。对于N*M的阵地每个位置有两种状态(部署、不部署),利用状态压缩的DP算法。借助位运算来判断冲突与否的问题。
要注意 &和<<运算符的优先级比较低,一般都加上括号。
源代码如下:
#include <iostream> using namespace std; #define MAX 60 //M=10时 所有可能方案数为60 int dp[103][MAX][MAX]; //dp[i][j][k]表示第i行状态为s[j],第i-1行状态为s[k] int s[MAX]; //对于M列 得出的所有可能状态 int num[MAX]; //对应s[] 每种状态中1的个数 int map[100]; //阵地地图 int realMax; //对于给定的M,得到的实际方案最大值 int getMaxScheme(int m) //由M获得一行的最大放置方案 { int top= 1<<m; int i,j=0; for(i=0;i<top;i++) { if((i & (i<<1)) || (i & (i<<2)))continue; s[j]=i; j++; } return j; } void setOneNumber() { int i,count,t; for(i=0;i<realMax;i++) { count=0; t=s[i]; while(t) { count++; t&=(t-1); } num[i]=count; } } inline int max(int a,int b) { if(a>b)return a; else return b; } int main() { freopen("in.txt","r",stdin); int N,M; cin>>N>>M; memset(map,0,sizeof(map)); memset(dp,-1,sizeof(dp)); int i,j,k,t; char charRow[11]; for(i=0;i<N;i++) { cin>>charRow; for(j=0;j<M;j++) { if(charRow[j]=='H')map[i]=map[i]+ (1<<j); //P P H P 对应 0 1 0 0 即4 反向倒置的,不过不影响 } // cout<<map[i]<<endl; } realMax=getMaxScheme(M); setOneNumber(); for(i=0;i<realMax;i++) { if((s[i]&map[0])==0)dp[0][i][0]=num[i]; } for(i=1;i<N;i++) { for(j=0;j<realMax;j++) //枚举第i行 { if(map[i]&s[j])continue; for(k=0;k<realMax;k++) //枚举第i-1行 { if(s[k]&s[j])continue; for(t=0;t<realMax;t++) //枚举第i-2行 { if(s[t]&s[j])continue; if(dp[i-1][k][t]==-1)continue; dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][t]+num[j]); } } } } int res=0; for(i=0;i<realMax;i++) { for(j=0;j<realMax;j++) { res=max(res,dp[N-1][i][j]); } } cout<<res<<endl; return 0; }