bzoj 1565(ACM恢复训练)

1565: [NOI2009]植物大战僵尸

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 3254  Solved: 1508
[Submit][Status][Discuss]

Description

Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏。Plants(植物)和Zombies(僵尸)是游戏的主角,其
中Plants防守,而Zombies进攻。该款游戏包含多种不同的挑战系列,比如Protect Your Brain、Bowling等等。其
中最为经典的,莫过于玩家通过控制Plants来防守Zombies的进攻,或者相反地由玩家通过控制Zombies对Plants发
起进攻。
 
现在,我们将要考虑的问题是游戏中Zombies对Plants的进攻,请注意,本题中规则与实际游戏有所不同。游戏中
有两种角色,Plants和Zombies,每个Plant有一个攻击位置集合,它可以对这些位置进行保护;而Zombie进攻植物
的方式是走到植物所在的位置上并将其吃掉。
 
游戏的地图可以抽象为一个N行M列的矩阵,行从上到下用0到N–1编号,列从左到右用0到M–1编号;在地图的每个
位置上都放有一个Plant,为简单起见,我们把位于第r行第c列的植物记为Pr, c。
 
Plants分很多种,有攻击类、防守类和经济类等等。为了简单的描述每个Plant,定义Score和Attack如下:
 
Score[Pr, c]
 
Zombie击溃植物Pr, c可获得的能源。若Score[Pr, c]为非负整数,则表示击溃植物Pr, c可获得能源Score[Pr, c]
,若为负数表示击溃Pr, c需要付出能源 -Score[Pr, c]。
 
Attack[Pr, c]
 
植物Pr, c能够对Zombie进行攻击的位置集合。
 
Zombies必须从地图的右侧进入,且只能沿着水平方向进行移动。Zombies攻击植物的唯一方式就是走到该植物所在
的位置并将植物吃掉。因此Zombies的进攻总是从地图的右侧开始。也就是说,对于第r行的进攻,Zombies必须首
先攻击Pr, M-1;若需要对Pr, c(0 ≤ c < M-1)攻击,必须将Pr,M-1, Pr, M-2 … Pr, c+1先击溃,并移动到位
置(r, c)才可进行攻击。
 
在本题的设定中,Plants的攻击力是无穷大的,一旦Zombie进入某个Plant的攻击位置,该Zombie会被瞬间消灭,
而该Zombie没有时间进行任何攻击操作。因此,即便Zombie进入了一个Plant所在的位置,但该位置属于其他植物
的攻击位置集合,则Zombie会被瞬间消灭而所在位置的植物则安然无恙(在我们的设定中,Plant的攻击位置不包
含自身所在位置,否则你就不可能击溃它了)。
 
Zombies的目标是对Plants的阵地发起进攻并获得最大的能源收入。每一次,你可以选择一个可进攻的植物进行攻
击。本题的目标为,制定一套Zombies的进攻方案,选择进攻哪些植物以及进攻的顺序,从而获得最大的能源收入

 

Input

第一行包含两个整数N, M,分别表示地图的行数和列数。
接下来N×M行描述每个位置上植物的信息。第r×M + c + 1行按照如下格式给出植物Pr, c的信息:
第一个整数为Score[Pr, c], 第二个整数为集合Attack[Pr, c]中的位置个数w,
接下来w个位置信息(r’, c’),表示Pr, c可以攻击位置第r’ 行第c’ 列。
1 ≤ N ≤ 20,1 ≤ M ≤ 30,-10000 ≤ Score ≤ 10000 。
 
 

Output

仅包含一个整数,表示可以获得的最大能源收入。
注意,你也可以选择不进行任何攻击,这样能源收入为0。
 
先tarjian,再跑最大权闭合子图。用topo序连边建图,标记不能被选的点。
第二份代码迷之WA。待调
  1 /**************************************************************
  2     Problem: 1565
  3     User: zqq
  4     Language: C++
  5     Result: Accepted
  6     Time:236 ms
  7     Memory:64028 kb
  8 ****************************************************************/
  9  
 10 #include<iostream>
 11 #include<cstdio>
 12 #include<cstring>
 13 #include<algorithm>
 14 using namespace std;
 15 #define maxn 2020
 16 #define maxm 2000020
 17 #define inf 0x3f3f3f3f
 18 struct node1{
 19     int to,next;
 20 }e1[maxm];
 21 struct node2{
 22     int to,next,f;
 23 }e2[maxm * 2];
 24 int head1[maxn],head2[maxn],cnt1,cur[maxn],cnt2 = 1,dfn[maxn],low[maxn],dfstime,belong[maxn],size[maxn];
 25 int stack[maxn],tops = -1,ins[maxn];
 26 int n,m,val[maxn],tot,src,sink,mincut,sum,dis[maxn],cant[maxn];
 27 int q[maxn * 20],hh,tt;
 28  
 29 inline void adde1(int x,int y){
 30     e1[++cnt1].to = y;
 31     e1[cnt1].next = head1[x];
 32     head1[x] = cnt1;
 33 }
 34 void tarjian(int now){
 35     dfn[now] = low[now] = ++dfstime;
 36     if ( !ins[now] ) stack[++tops] = now , ins[now] = 1;
 37     for (int i = head1[now] ; i ; i = e1[i].next){
 38         if ( !dfn[e1[i].to]  ){
 39             tarjian(e1[i].to) , low[now] = min(low[now],low[e1[i].to]);
 40         }
 41         if ( ins[e1[i].to] ){
 42             low[now] = min(low[now],dfn[e1[i].to]);
 43         }
 44     }
 45     if ( dfn[now] == low[now] ){
 46         int x = stack[tops--];
 47         while ( x != now ){
 48             ins[x] = 0;
 49             size[now]++;
 50             belong[x] = now;
 51             x = stack[tops--];
 52         }
 53         belong[now] = now , ins[now] = 0 , size[now]++;
 54     }
 55 }
 56 inline void bfs2(){
 57     hh = tt = 0;
 58     for (int i = 1 ; i <= n * m ; i++)
 59         if ( belong[i] == i && size[i] > 1 ) q[tt++] = i , cant[i] = 1;
 60     while ( hh < tt ){
 61         int now = q[hh++];
 62         for (int i = head1[now] ; i ; i = e1[i].next){
 63             if ( !cant[e1[i].to] ){
 64                 cant[e1[i].to] = 1;
 65                 q[tt++] = e1[i].to;
 66             }   
 67         }   
 68     }
 69 }
 70 inline void adde2(int x,int y,int c){
 71     e2[++cnt2].to = y;
 72     e2[cnt2].next = head2[x];
 73     e2[cnt2].f = c;
 74     head2[x] = cnt2;
 75     e2[++cnt2].to = x;
 76     e2[cnt2].next = head2[y];
 77     e2[cnt2].f = 0;
 78     head2[y] = cnt2;
 79 }
 80 inline bool bfs(){
 81     memset(dis,0,sizeof(dis));
 82     hh = tt = 0;
 83     q[tt++] = src;
 84     dis[src] = 1;
 85     while ( hh < tt ){
 86         int now = q[hh++];
 87         for (int i = head2[now] ; i ; i = e2[i].next){
 88             if ( e2[i].f && !dis[e2[i].to] ){
 89                 dis[e2[i].to] = dis[now] + 1;
 90                 q[tt++] = e2[i].to;
 91             }
 92         }
 93     }
 94     return dis[sink] > 0;
 95 }
 96 int dfs(int now,int delta){
 97     if ( now == sink ) return delta;
 98     else{
 99         int ret = 0;
100         for (int &i = cur[now] ; i && delta ; i = e2[i].next){
101             if ( e2[i].f && dis[now] + 1 == dis[e2[i].to] ){
102                 int dd = dfs(e2[i].to,min(delta,e2[i].f));
103                 ret += dd;
104                 delta -= dd;
105                 e2[i].f -= dd;
106                 e2[i ^ 1].f += dd;
107                 if ( !delta ) return ret;
108             }
109         }
110         if ( delta ) dis[now] = -1;
111         return ret;
112     }
113 }
114 int main(){
115     scanf("%d %d",&n,&m);
116     for (int i = 1 ; i <= n * m ; i++){
117         int w;
118         scanf("%d %d",&val[i],&w);
119         for (int j = 1 ; j <= w ; j++){
120             int r,c;
121             scanf("%d %d",&r,&c);
122             adde1(i,r * m + c + 1);
123         }
124     }
125     for (int i = 1 ; i <= n ; i++){
126         for (int j = 2 ; j <= m ; j++){
127             adde1((i - 1) * m + j,(i - 1) * m + j - 1);
128         }
129     }
130     for (int i = 1 ; i <= n * m ; i++){
131         if ( !dfn[i] ) 
132             tarjian(i);
133     }
134     bfs2();
135 //  for (int i = 1 ; i <= n * m ; i++) cout<<cant[i]<<" ";
136 //  cout<<endl;
137     for (int i = 1 ; i <= n * m ; i++){
138         if ( !cant[i] ){
139             ++tot;
140             if ( val[i] > 0 ) sum += val[i];
141         }
142     }
143     src = n * m + 1 , sink = n * m + 2;
144     for (int i = 1 ; i <= n * m ; i++){
145         for (int j = head1[i] ; j ; j = e1[j].next){
146             if ( belong[e1[j].to] != belong[i] && !cant[belong[i]] && !cant[belong[e1[j].to]]  ){
147                 adde2(belong[e1[j].to],belong[i],inf);
148             }
149         }
150     }
151     for (int i = 1 ; i <= n * m ; i++){
152         if ( !cant[i] ){
153             if ( val[i] > 0 ) adde2(src,i,val[i]);
154             if ( val[i] < 0 ) adde2(i,sink,-val[i]);
155         }
156     }
157     while ( bfs() ){
158         for (int i = 1 ; i <= sink ; i++) cur[i] = head2[i];
159         mincut += dfs(src,inf);
160     }
161     //1cout<<sum<<" "<<mincut<<endl;
162     printf("%d",sum - mincut);
163     return 0;
164 }
View Code
  1 /**************************************************************
  2     Problem: 1565
  3     User: zqq
  4     Language: C++
  5     Result: Wrong_Answer
  6 ****************************************************************/
  7  
  8 #include<iostream>
  9 #include<cstdio>
 10 #include<cstring>
 11 #include<algorithm>
 12 using namespace std;
 13 #define maxn 1020
 14 #define maxm 2000020
 15 #define inf 0x3f3f3f3f
 16  
 17 struct node{
 18     int next,to,f;
 19 }e2[maxn],e[maxm * 2];
 20 int head[maxn],cur[maxn],head2[maxn],cnt = 1;
 21 int n,m,ans,v[maxn];
 22 int dfn[maxn],low[maxn],stack_[maxn],tops,ins[maxn],dfstime,sz[maxn],belong[maxn],vis[maxn],deg[maxn],can[maxn];
 23 int q[maxn],tt,hh,dis[maxn],S,T;
 24  
 25 inline void adde(int x,int y){
 26     e[++cnt].to = y;
 27     e[cnt].next = head[x];
 28     head[x] = cnt;
 29 }
 30 inline void adde(int x,int y,int f){
 31     e[++cnt].to = y;
 32     e[cnt].next = head[x];
 33     e[cnt].f = f;
 34     head[x] = cnt;
 35     e[++cnt].to = x;
 36     e[cnt].next = head[y];
 37     head[y] = cnt;
 38 }   
 39 inline void adde2(int x,int y){
 40     e2[++cnt].to = y;
 41     e2[cnt].next = head2[x];
 42     head2[x] = cnt;
 43 }
 44 void dfs(int x){
 45     dfn[x] = low[x] = ++dfstime;
 46     if ( !ins[x] ) stack_[++tops] = x , ins[x] = 1;
 47     for (int i = head[x] ; i ; i = e[i].next){
 48         int to = e[i].to;
 49         if ( !dfn[to] ) dfs(to) , low[x] = min(low[x],low[to]);
 50         else if ( ins[to] ) low[x] = min(low[x],low[to]);
 51     }
 52     if ( low[x] == dfn[x] ){
 53         int now = stack_[tops--];
 54         while ( now != x ){
 55             sz[x]++ , belong[now] = x , ins[now] = 0;
 56             now = stack_[tops--];
 57         }
 58         sz[x]++ , belong[x] = x , ins[x] = 0;
 59     }
 60 }
 61  
 62 void topo(){
 63     for (int i = 1 ; i <= n * m ; i++){
 64         if ( sz[i] == 1 ) can[i] = 1;
 65         if ( !deg[i] && belong[i] == i ) q[tt++] = i;
 66     }
 67     while ( hh < tt ){
 68         int x = q[hh++];
 69         for (int i = head2[x] ; i ; i = e2[i].next){
 70             int to = e2[i].to;
 71             deg[to]--;
 72             if ( !can[x] ) can[to] = 0;
 73             if ( !deg[to] ) q[tt++] = to;
 74         }
 75     }
 76 }
 77 void dfs2(int x){
 78     if ( vis[x] || !can[x] ) return;
 79     vis[x] = 1;
 80     if ( v[x] > 0 ) ans += v[x] , adde(S,x,v[x]);
 81     else if ( v[x] < 0 ) adde(x,T,-v[x]);
 82     for (int i = head2[x] ; i ; i = e2[i].next){
 83         adde(e2[i].to,x,inf);
 84         dfs2(e2[i].to);
 85     }
 86 }
 87  
 88 void init(){
 89     S = n * m + 1 , T = S + 1 , cnt = 0;
 90     for (int i = 1 ; i <= n * m ; i++) 
 91         for (int j = head[i] ; j ; j = e[j].next)
 92             if ( belong[i] != belong[e[j].to] ) 
 93                 adde2(belong[i],belong[e[j].to]) , deg[belong[e[j].to]]++;
 94     topo();
 95     cnt = 1 , memset(head,0,sizeof(head)) , memset(e,0,sizeof(e));
 96     for (int i = 0 ; i < tt ; i++) if ( !vis[q[i]] ) dfs2(q[i]);
 97 }
 98 bool bfs(){
 99     memset(dis,0,sizeof(dis));
100     tt = hh = 0;
101     q[tt++] = S , dis[S] = 1;
102     while ( hh < tt ){
103         int x = q[hh++];
104         for (int i = head[x] ; i ; i = e[i].next){
105             if ( e[i].f && !dis[e[i].to] ){
106                 dis[e[i].to] = dis[x] + 1;
107                 q[tt++] = e[i].to;
108             }
109         }
110     }
111     return dis[T];
112 }
113 int dfs2(int x,int delta){
114     if ( x == T || !delta ) return delta;
115     int res = 0;
116     for (int &i = cur[x] ; i ; i = e[i].next){
117         if ( e[i].f && dis[e[i].to] == dis[x] + 1 ){
118             int d = dfs2(e[i].to,min(e[i].f,delta));
119             e[i].f -= d , e[i ^ 1].f += d;
120             delta -= d , res += d;
121             if ( !delta ) return res;
122         }
123     }
124     if ( delta ) dis[x] = -1;
125     return res;
126 }   
127 int main(){
128     scanf("%d %d",&n,&m);
129     for (int i = 1 ; i <= n ; i++) for (int j = 1 ; j <= m ; j++){
130         int w,d,x,y;
131         scanf("%d %d",&d,&w);
132         v[(i - 1) * m + j] = d;
133         for (int k = 1 ; k <= w ; k++){
134             scanf("%d %d",&x,&y) , x++ , y++;
135             adde((i - 1) * m + j,(x - 1) * m + y);
136         }
137         if ( j > 1 ) adde((i - 1) * m + j,(i - 1) * m + j - 1);
138     }
139     for (int i = 1 ; i <= n * m ; i++) 
140         if ( !dfn[i] ) dfs(i);
141     init();
142     while ( bfs() ){
143         memcpy(cur,head,sizeof(head));
144         ans -= dfs2(S,inf);
145     }
146     printf("%d\n",ans);
147     return 0;
148 }
View Code

 

posted @ 2018-06-29 12:05  zhangqingqi  阅读(158)  评论(0编辑  收藏  举报