• 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 }
  • 相关阅读:
    07_控制线程_join_线程插队
    06_线程的生命周期及状态
    05_线程间通信
    04_线程的创建和启动_使用Callable和Future的方式
    03_线程的创建和启动_实现Runnable接口方式
    02_线程的创建和启动_继承Thread方式
    01_基础知识
    07_XPath_02_常用语法
    二叉树分层遍历
    [LeetCode] Binary Tree Level Order Traversal II
  • 原文地址:https://www.cnblogs.com/njczy2010/p/3940098.html
Copyright © 2020-2023  润新知