poj 1185 状态压缩 动态规划

题意:‘H’是山地,‘P’是平原,在平原上可以放置炮兵,攻击范围为图中黑色部分,炮兵不能放置在其他炮兵的攻击范围内,问最多能放多少个炮兵?

分析:用一个整数s表示一行的状态,s的第k位为1表示这一行第k列放置了炮兵。cnt[s] 表示 s的1的个数,即放置了炮兵的个数。

d[r][i][j]表示第 r 行状态为 i, r-1 行状态为 j 的最大炮兵数,d[r][i][j] = max( d[r-1][j][k] + cnt[i] );  其中j k 与 i 不冲突。

每行最多有10个格子,状态为2^10,但有一些状态是非法的,合法状态在60个以内,所以要先预处理出所有合法状态。

 

 

const int N = 101, M = 15, K = 65;
 
 int n, m, ans;
 int d[N][K][K];
 
 int s[K], cnt[K], p;
 int a[N];
 char c[N][M];
 
 void init(){
     FOR(i,0,1<<m){
         if(i&(i<<1) || i&(i<<2)) continue;
         s[p]=i;
         FOR(j,0,m) if(i&(1<<j)) cnt[p]++;
         p++;
     }
 }
 
 void read(){
     cin>>n>>m;
     FOR(i,0,n) {
         cin>>c[i];
         FOR(j,0,m) if(c[i][j]=='H') a[i]|=1<<j;
     }
 }
 
 void dp(){
     FOR(k,0,p) {
         if(a[0]&s[k]) continue;
         d[0][k][0]=cnt[k];
         checkmax(ans, d[0][k][0]);
     }
     FOR(i,1,n){
         FOR(k,0,p){
             if(a[i]&s[k])continue;
             FOR(u,0,p){
                 if(s[k]&s[u])continue;
                 FOR(v,0,p){
                     if(s[v]&s[k])continue;
                     checkmax(d[i][k][u], d[i-1][u][v] + cnt[k]);
                     checkmax(ans, d[i][k][u]);
                 }
             }
         }
     }
     
     cout<<ans<<endl;
 }
 
 int main(){
     #ifndef ONLINE_JUDGE
     freopen("in.txt","r",stdin);
     //freopen("out.txt","w",stdout);
     #endif
 
     read();
     init();
     dp();
 
     return 0;
 }

 

转载于:https://www.cnblogs.com/ts65213/archive/2013/05/16/3081574.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值