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\n",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",n);
 97         ini();
 98         solve();
 99         printf("%d\n",ma);
100         //cout<<tot<<endl;
101     }
102
103     return 0;
104 }
时间: 2024-12-26 06:24:53

ZOJ 3306 状压dp的相关文章

zoj 3675 状压dp

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4918 昨天的排位,最初我还以为思维题,然后队友说状压DP,直接放弃,赛后看了队友的代码,在搜下网上的,发现队友的代码居然是最短的,膜拜啊~~~~~~~ 思路是队友 A.L.的 dp[s]=min(dp[s],dp[s']+1) 其中s'可以由s通过一次正着剪指甲或者反着剪指甲达到 至于内层循环,0-m,是因为----从剪指甲刀的最后一位看,最后一位从0移动到m,足够所有情况了

zoj 3471 状压DP

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4257 难度远不及我之前发的... 可是我第一次的思路居然错了,由于dp方程想设计成二维,可是弄错.也没发现原因.,. 改为一维:dp[s]:状态为s的时候,得到的最大能量,当中s第i位为1表示,i已经被撞毁 #include <cstdio> #include <cstring> #include <algorithm> #include <s

Most Powerful(ZOJ 3471状压dp)

题意:n个原子,两两相撞其中一个消失,产生能量,给出任意两原子相撞能产生的能量,求能产生的最大能量. 分析:dp[i]表示情况为i时产生的最大能量 /*#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector>

Survival(ZOJ 2297状压dp)

题意:有n个怪,已知杀死第i个怪耗费的血和杀死怪恢复的血,和杀死boss耗的血,血量不能超过100,若过程中血小于0,则失败,问 是否能杀死boss(boss最后出现). 分析:就是求杀死n个怪后剩余的最大血量 dp[i]表示杀怪情况为i(0未杀,1已杀)时剩余最大血量,注意血量上限为100,过程中血小于0,则失败即可. #include <map> #include <set> #include <list> #include <cmath> #inclu

Travel(HDU 4284状压dp)

题意:给n个城市m条路的网图,pp在城市1有一定的钱,想游览这n个城市(包括1),到达一个城市要一定的花费,可以在城市工作赚钱,但前提有工作证(得到有一定的花费),没工作证不能在该城市工作,但可以走,一个城市只能工作一次,问pp是否能游览n个城市回到城市1. 分析:这个题想到杀怪(Survival(ZOJ 2297状压dp) 那个题,也是钱如果小于0就挂了,最后求剩余的最大钱数,先求出最短路和 Hie with the Pie(POJ 3311状压dp) 送披萨那个题相似. #include <

状压DP [ZOJ 3471] Most Powerful

Most Powerful Time Limit: 2 Seconds      Memory Limit: 65536 KB Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a

ZOJ 3471 Most Powerful 状压DP

水题,一维的DP,表示还剩哪些atom的时候能获得的最大能量 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <string> #include <queue> #include <deque> #include <

ZOJ 3471 Most Powerful(状压DP)

Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way every two at

ZOJ 3471 Most Powerful(状压DP)

Description Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way