bzoj 1565(ACM恢复训练)
1565: [NOI2009]植物大战僵尸
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 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。待调
View Code
View Code
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 }
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 }