zoukankan      html  css  js  c++  java
  • ZOJ 3306 状压dp

    转自:http://blog.csdn.net/a497406594/article/details/38442893

    Kill the Monsters

    Time Limit: 7 Seconds Memory Limit: 32768 KB

    In order to celebrate the 8th anniversary of ZOJ, watashi introduces a strange game to other ZJU ACM team members. The board of the game consists of 20X20 grids.

    There're some monsters in the grid and 40 buttons along the board. Each row and column is controlled by a single button, while each button can be pushed ONLY ONCE.

    • If you push a row-controlling button, the health point of all the monsters in the corresponding row will decrease 1.
    • If you push a column-controlling button, the health point of all the monsters in the corresponding column will decrease 1.

    The health point of each monster is 2 initially, and if the monster's health point is 0, we say that the monster has been killed. The goal of the game is to kill as many monsters as possible and you cannot push more than N buttons.

    Though Watashi plays the game day and night, he cannot always achieve the perfect goal. Please help him to find the best solution of some specific boards.

    Input

    The first line of each test case contains the numbers N ( 1 <= N <= 40 ).

    Then there're 20 lines, each with 20 characters. The jth character in the ith line correspond to the state in grid (i, j). '.' for the empty grid, '#' for a monster.

    The input will contain no more than 10 test cases.

    The last test case is followed by one zero.

    Output

    For each test case output one number, the maximum number of dead monsters.

    Sample Input

    3
    ....................
    ....................
    ..###...............
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    ....................
    10
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    ####################
    0
    

    Sample Output

    2
    25
    

    题意:每次给出一张20*20的图,#表示拥有两滴血的怪物,有两种减怪物血的方式,一种是整列减1滴血,另一种是整行减1滴血,且每行每列只能减一次。提供n次,问最多能杀掉多少怪物。

    思路:主要还是围绕着消除哪些行跟哪些列,并使行+列=n,这样很容易就相当枚举其中一个,行不容易处理,反而列可以用状压dp进行处理。用1表示选取了当前列。接下来只要选取所在列下,对能每行能消除的个数进行排序,选取最多能消除的前几行。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cstdio>
      5 #include<algorithm>
      6 #include<cmath>
      7 #include<queue>
      8 #include<map>
      9 #include<vector>
     10 
     11 #define N 25
     12 #define M 15
     13 #define mod 1000000007
     14 #define mod2 100000000
     15 #define ll long long
     16 #define maxi(a,b) (a)>(b)? (a) : (b)
     17 #define mini(a,b) (a)<(b)? (a) : (b)
     18 
     19 using namespace std;
     20 
     21 int n;
     22 char s[N][N];
     23 int have[N];
     24 int ma;
     25 int tot;
     26 int cou[N];
     27 int cc[(1<<20)+10];
     28 int now;
     29 
     30 void ini1()
     31 {
     32     memset(cc,0,sizeof(cc));
     33     for(int i=0;i<(1<<20);i++)
     34     {
     35         int cnt=0;
     36         for(int j=0;j<20;j++)
     37             if(i&(1<<j))
     38                 cnt++;
     39         cc[i]=cnt;
     40     }
     41 }
     42 
     43 void ini()
     44 {
     45     int i,j;
     46     ma=0;
     47     memset(have,0,sizeof(have));
     48     for(i=0;i<20;i++){
     49         scanf("%s",s[i]);
     50     }
     51     for( i=0;i<20;i++)
     52         for( j=0;j<20;j++)
     53             if(s[i][j]=='#')
     54                 have[i]+=(1<<j);
     55 
     56 }
     57 
     58 bool cmp(int i,int j)
     59 {
     60     return i>j;
     61 }
     62 
     63 void solve()
     64 {
     65     int o,i,j,temp;
     66     for(o=1;o<tot;o++)
     67     {
     68         memset(cou,0,sizeof(cou));
     69         if(cc[o]>n) continue;
     70        // printf(" o=%d now=%d
    ",o,now);
     71         for(i=0;i<20;i++){
     72             cou[i]=cc[ o &have[i] ];
     73         }
     74         sort(cou,cou+20,cmp);
     75         //for(j=0;j<20;j++) printf(" j=%d cou=%d")
     76         temp=0;
     77         for(j=0;j<n-cc[o] && j<20;j++){  //注意这里j<20
     78             temp+=cou[j];
     79         }
     80         ma=max(ma,temp);
     81     }
     82 }
     83 
     84 int main()
     85 {
     86    // freopen("data.in","r",stdin);
     87    // freopen("data.out","w",stdout);
     88     //scanf("%d",&T);
     89    // for(int cnt=1;cnt<=T;cnt++)
     90    // while(T--)
     91     tot=1<<20;
     92     ini1();
     93     while(scanf("%d",&n)!=EOF)
     94     {
     95         if(n==0) break;
     96         //printf(" %d
    ",n);
     97         ini();
     98         solve();
     99         printf("%d
    ",ma);
    100         //cout<<tot<<endl;
    101     }
    102 
    103     return 0;
    104 }
  • 相关阅读:
    python的变量,对象的内存地址以及参数传递过程
    win10环境pycharm社区版创建django项目
    组合,菱形继承,子类重用父类2,深度广度查找
    类内的函数共享给对象使用
    模块与面向对象初解
    正则模块,sys模块
    包介绍,与日记模块
    模块运用,文件搜索
    递归,匿名函数
    生成器与简写
  • 原文地址:https://www.cnblogs.com/njczy2010/p/3940098.html
Copyright © 2011-2022 走看看