HDU 4539 郑厂长系列故事——排兵布阵

http://acm.hdu.edu.cn/showproblem.php?pid=4539

郑厂长系列故事——排兵布阵

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1708    Accepted Submission(s): 620

Problem Description

  郑厂长不是正厂长
  也不是副厂长
  他根本就不是厂长
  事实上
  他是带兵打仗的团长

  一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。
  根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
  现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。

Input

输入包含多组测试数据;
每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;
接下来的n行,每行m个数,表示n*m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。

Output

请为每组数据计算并输出最多能安排的士兵数量,每组数据输出一行。

Sample Input

6 6

0 0 0 0 0 0

0 0 0 0 0 0

0 0 1 1 0 0

0 0 0 0 0 0

0 0 0 0 0 0

0 0 0 0 0 0

Sample Output

2

分析:曼哈顿距离为2,一个米,点就是中心,距离都是2,跟poj1181一样,稍微改一下就行。数组开大一点。int dp[102][202][202];

数组开得太小,一直wa,伤心了

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[102][202][202];
int n,m,p,sta[4096],sum[4096];
int count(int n)
 {
     int num = 0;
     while(n){
        n &= (n - 1);
        num++;
       }
     return num;
 }
void init()
{
    int i;
    for(i=0;i<1<<m;i++)
    {
        if((i<<2)&i)
           continue;
         sum[p]=count(i);
        sta[p++]=i;

    }
}
int fit(int x,int y)
{
    if(x&y)
       return 0;
    else
       return 1;
}
int match(int x,int y)
{
    if((x<<1)&y)
        return 0;
     if(x>>1&y)
        return 0;
    return 1;
}
 int main()
 {
      int i,j,a[105],tem,k,r;
      while(~scanf("%d%d",&n,&m))
      {
               p=0;
           memset(dp,-1,sizeof(dp));
            memset(a,0,sizeof(a));
            memset(sta,0,sizeof(sta));
            memset(sum,0,sizeof(sum));
          for(i=1;i<=n;i++)
          {
            for(j=1;j<=m;j++)
            {
                scanf("%d",&tem);
                if(tem==0)
                     a[i]+=1<<m-j;
            }
          }
       init();
        for(i=0;i<p;i++)
        {
            if(fit(sta[i],a[1]))
              {
                  dp[1][i][0]=sum[i];

              }
        }

     for(i=2;i<=n;i++)
        {
            for(j=0;j<p;j++)
             {

                 if(!fit(sta[j],a[i]))
                    continue;
                 for(k=0;k<p;k++)
                   {
                       if(!fit(sta[k],a[i-1]))
                          continue;
                      if(!match(sta[j],sta[k]))
                           continue;
                           for(r=0;r<p;r++)
                          {
                                if(!fit(sta[r],sta[j]))
                                    continue;
                               if(!fit(sta[r],a[i-2]))
                                  continue;
                             if(!match(sta[k],sta[r]))
                                 continue;
                               dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][r]+sum[j]);

                          }
                   }
             }
        }
          int ans=0;
        for(i=0;i<p;i++)
          for(j=0;j<p;j++)
         {
             ans=max(ans,dp[n][i][j]);
         }
         printf("%d\n",ans);
      }
      return 0;
 }

HDU 4539 郑厂长系列故事——排兵布阵

时间: 2024-10-01 05:10:36

HDU 4539 郑厂长系列故事——排兵布阵的相关文章

HDU 4539 郑厂长系列故事——排兵布阵 (状态压缩DP)

中文题,题意不再累赘. 思路:对于第 i 行的放士兵,影响它的只有第 i-1 行和 i-2 行,所以暴力枚举符合这三行的状态 state[i],state[j],state[k].  接下来就是二进制的巧妙应用了. 具体题解看代码注释!!! #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #include<cmath&

HDU 4539郑厂长系列故事――排兵布阵(状压DP)

HDU 4539  郑厂长系列故事――排兵布阵 基础的状压DP,首先记录先每一行可取的所哟状态(一行里互不冲突的大概160个状态), 直接套了一个4重循环居然没超时我就呵呵了 1 //#pragma comment(linker,"/STACK:102400000,102400000") 2 #include <map> 3 #include <set> 4 #include <stack> 5 #include <queue> 6 #i

HDU 4539 郑厂长系列故事――排兵布阵(状态压缩)

郑厂长系列故事--排兵布阵 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1954    Accepted Submission(s): 701 Problem Description 郑厂长不是正厂长 也不是副厂长 他根本就不是厂长 事实上 他是带兵打仗的团长 一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵. 根据以往的战

HDU 4539 郑厂长系列故事――排兵布阵

/* 曼哈顿距离的定义是:两个点的坐标为(x1,y1),(x2,y2),两点的曼哈顿距离为|x1-x2|+|y1-y2| 题意:题上要求是两个士兵的距离不能是曼哈顿距离为2,意思就是这个点在同一行同一列不能相间,这个点的左上,左下,右上,右下角不能有 士兵. 思路:dp+状态压缩dp[i][j][k]定义的状态为i是当前行,j为当前行的状态,k为上一行的状态类似炮兵阵地 */ #include<stdio.h> #include<string.h> #define Max(a,b)

HDU 4539 郑厂长系列故事——排兵布阵 &lt;&lt;状压dp

思路 被这道题折磨死了,只是发上来纪念一下,思路同方格取数(1),我已经疯了! 代码 1 #include<bits/stdc++.h> 2 using namespace std; 3 int maze[110][15]; 4 int n,m; 5 vector<int> all[110]; 6 int dp[110][200][200]; 7 int num[1<<10]; 8 bool check(int r,int state) 9 { 10 for(int i

HDU ACM 4539 郑厂长系列故事——排兵布阵-&gt;状态压缩DP

分析:dp[i][j][k]表示第i行状态为j,i-1行状态为k时的客房士兵的最大值. 曼哈顿距离是指:|x1-x2|+|y1-y2|. 当前行不仅与前一行有关,还和前两行有关,所以开数组的时候还要记录前两行的状态,所以开设三维数组. 每行可压缩为二进制集合,状态dp[i][j][k]为第i行为集合j,第i-1行为集合k,则状态方程dp[i][j][k] = max{dp[i-1][k][r]+cnt[j]  | 状态i,j,k要能够共存}(cnt[j]为j在二进制下的1的个数,即士兵数).第一

[状压dp]HDOJ4539 郑厂长系列故事——排兵布阵

中文题,题意不再赘述 对于“?”这一格,它所能攻击到的(曼哈顿距离为2的) 前方的 即“√”的四个位置 那么与此格有关的即它前方两行(即状压这两行) 首先预处理每行能满足的: i 和(i<<2)不能同时放 然后分别枚举前一行和再前一行的所有状态(每一行的状态至多只有2^10=1024个) 判断能否共存 注意mp==1处才能放,mp==0处不能放 HDOJ 4539

HDU - 4529 郑厂长系列故事――N骑士问题 (状态压缩DP)

Description 郑厂长不是正厂长 也不是副厂长 他根本就不是厂长 还是那个腾讯公司的码农 一个业余时间喜欢下棋的码农 最近,郑厂长对八皇后问题很感兴趣,拿着国际象棋研究了好几天,终于研究透了.兴奋之余,坐在棋盘前的他又开始无聊了.无意间,他看见眼前的棋盘上只摆了八个皇后,感觉空荡荡的,恰好又发现身边还有几个骑士,于是,他想把这些骑士也摆到棋盘上去,当然棋盘上的一个位置只能放一个棋子.因为受八皇后问题的影响,他希望自己把这些骑士摆上去之后,也要满足每2个骑士之间不能相互攻击. 现在郑厂长想

[AC自动机+状压dp] hdu 4534 郑厂长系列故事——新闻净化

题意:中文的题目,意思就是说有很多串,每个串都有权值,权值为999的串必须出现,-999的串必须不出现.权值在-999~999之间. 然后必须出现的串不超过8个.然后给一个全为小写目标串,问最少需要删除多少个字母才能够保证必须出现的串都出现,次数一样保证权值最大.输出次数和权值. 然后根据样例,那些必须出现的串,其实权值是0. 思路: 很明显一开始建自动机构成trie图,但是需要注意的就是mark和sum的更新.个人是把所有中间的节点的sum全部赋值成了-inf. 接着只有8个必须出现的串,所以