P4304 [TJOI2013]攻击装置 网络流
Posted orangeko
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4304 [TJOI2013]攻击装置 网络流相关的知识,希望对你有一定的参考价值。
题目描述
给定一个01矩阵,其中你可以在0的位置放置攻击装置。 每一个攻击装置(x,y)都可以按照“日”字攻击其周围的8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1),(x+1,y+2),(x+2,y+1)
求在装置互不攻击的情况下,最多可以放置多少个装置。
输入格式
第一行一个整数N,表示矩阵大小为N*N。
接下来N行每一行一个长度N的01串,表示矩阵。
输出格式
一个整数,表示在装置互不攻击的情况下最多可以放置多少个装置。
输入输出样例
输入 #1
3 010 000 100
输出 #1
4
说明/提示
30%数据N<=50
100%数据 N<=200
思路
方格取数问题加强版、骑士共存问题的魔改
做过任意一个就可以秒了
CODE
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 6 7 const int maxn = 1e6 + 7; 8 9 const int inf = 0x3f3f3f3f; 10 11 12 13 template<class T>inline void read(T &res) 14 15 { 16 17 char c;T flag=1; 18 19 while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)flag=-1;res=c-‘0‘; 20 21 while((c=getchar())>=‘0‘&&c<=‘9‘)res=res*10+c-‘0‘;res*=flag; 22 23 } 24 25 26 27 struct edge{int from,to,cap,flow;}; 28 29 int s, t, n, m; 30 31 struct isap 32 33 { 34 35 int n,s,t,p[maxn],d[maxn],cur[maxn],num[maxn]; 36 37 bool vis[maxn]; 38 39 vector<int>g[maxn]; 40 41 vector<edge>edges; 42 43 void init(int n,int s,int t) { 44 45 this->n = n; 46 47 this->s = s; 48 49 this->t = t; 50 51 for(int i = 1;i <= n;i++) g[i].clear(); 52 53 edges.clear(); 54 55 } 56 57 void addegde(int from,int to,int cap) { 58 59 edges.push_back((edge){from, to, cap, 0}); 60 61 edges.push_back((edge){to, from, 0, 0}); 62 63 int m = edges.size(); 64 65 g[from].push_back(m-2); 66 67 g[to].push_back(m-1); 68 69 } 70 71 72 73 int augment() {///找增广路 74 75 int x = t,a = inf; 76 77 while(x!=s) { 78 79 a = min(a, edges[p[x]].cap - edges[p[x]].flow); 80 81 x = edges[p[x]].from; 82 83 } 84 85 x=t; 86 87 while(x != s) { 88 89 edges[p[x]].flow += a; 90 91 edges[p[x]^1].flow = -a; 92 93 x = edges[p[x]].from; 94 95 } 96 97 return a; 98 99 } 100 101 int maxflow() {///更新最大流 102 103 int flow = 0; 104 105 memset(num, 0, sizeof(num)); 106 107 memset(cur, 0, sizeof(cur)); 108 109 for(int i = 1; i <= n; i++) num[d[i]]++; 110 111 int x = s; 112 113 while(d[s] < n) {///最长的一条链上,最大的下标是nv-1,如果大于等于nv说明已断层 114 115 if(x == t) { 116 117 flow += augment(); 118 119 x = s;//回退 120 121 } 122 123 bool ok = 0; 124 125 for(int i = cur[x]; i < g[x].size(); i++) { 126 127 edge &e = edges[g[x][i]]; 128 129 if(d[x] == d[e.to] + 1 && e.cap > e.flow) { 130 131 p[e.to] = g[x][i]; 132 133 cur[x] = i;x = e.to; 134 135 ok = 1; 136 137 break; 138 139 } 140 141 } 142 143 if(!ok) { 144 145 int m = n-1; 146 147 for(int i = 0; i < g[x].size();i++) { 148 149 edge &e=edges[g[x][i]]; 150 151 if(e.cap>e.flow) m=min(m,d[e.to]); 152 153 } 154 155 num[d[x]]--; 156 157 if(!num[d[x]]) break; 158 159 d[x] = m+1; 160 161 num[d[x]]++; 162 163 cur[x] = 0; 164 165 if(x != s) x = edges[p[x]].from; 166 167 } 168 169 } 170 171 return flow; 172 173 } 174 175 }ISAP; 176 177 inline int id(int x, int y) { 178 return (x-1) * n + y; 179 } 180 181 char a[507][507]; 182 183 int dr[8] = {-2, -2, -1, -1, 1, 1, 2, 2}; 184 int dc[8] = {1, -1, 2, -2, 2, -2, 1, -1}; 185 186 int main() 187 { 188 read(n); 189 190 memset(a, 0, sizeof(a)); 191 s = 0, t = n * n + 1; 192 ISAP.init(n * n * 2, s, t); 193 for ( int i = 1; i <= n; ++i ) { 194 for ( int j = 1; j <= n; ++j ) { 195 cin >> a[i][j]; 196 if(a[i][j] == ‘1‘) 197 ++m; 198 } 199 } 200 // for ( int i = 1; i <= n; ++i ) { 201 // for ( int j = 1; j <= n; ++j ) { 202 // cout << a[i][j]; 203 // } 204 // cout << endl; 205 // } 206 for ( int i = 1; i <= n; ++i ) { 207 for ( int j = 1; j <= n; ++j ) { 208 if(a[i][j] == ‘1‘) 209 continue; 210 if((i + j) & 1) { 211 ISAP.addegde(s, id(i, j), 1); 212 for ( int k = 0; k <= 7; ++k ) { 213 int x = i + dr[k], y = j + dc[k]; 214 if(x < 1 || x > n || y < 1 || y > n) { 215 continue; 216 } 217 ISAP.addegde(id(i, j), id(x, y), 1); 218 } 219 } 220 else { 221 ISAP.addegde(id(i, j), t, 1); 222 } 223 } 224 } 225 int maxflow = ISAP.maxflow(); 226 //dbg(maxflow); 227 int ans = n * n - m - maxflow; 228 cout << ans << endl; 229 return 0; 230 }
以上是关于P4304 [TJOI2013]攻击装置 网络流的主要内容,如果未能解决你的问题,请参考以下文章