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 }
  • 相关阅读:
    使用私有api实现自己的iphone桌面,并根据app的使用次数对app排序
    坐标系的属性
    带坐标轴的几何画板
    空间几何体的直观图matlab
    设置npm的registry
    (原创)机器学习之numpy库中常用的函数介绍(一)
    (原创)交叉编译 tesseract
    (原创)计算机视觉之数学原理-基础篇
    (原创)nRF51 DFU 初始化包介绍及生成工具
    (原创)使用nRF51822/nRF51422创建一个简单的BLE应用 ---入门实例手册(中文)之五
  • 原文地址:https://www.cnblogs.com/njczy2010/p/3940098.html
Copyright © 2011-2022 走看看