zoukankan      html  css  js  c++  java
  • 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 }
    View Code
  • 相关阅读:
    C# 获取 域(AD) 用户信息
    如何在 MOSS 2007 启用 Session
    安装 卸载 回收 sharepoint 解决方案 moss wss wsp
    [转]挑战Windows极限:物理内存
    霍特卡的 CSLA.Net 3.6 Windows及Silverlight的正式版 昨天发布 同时CSLA.Net 业务对象 2008 英文版图书可以网上订购
    转帖如何在不联网的情况下安装 Silverlight Tools
    jQuery 选择器的使用
    关闭 Windows Server 2008 用户权限控制(UAC)
    jQuery 的第一个例子
    jQuery for Asp.Net 一步一步从入门到精通(附 jQuery API 彩色大图)
  • 原文地址:https://www.cnblogs.com/orangeko/p/13281079.html
Copyright © 2011-2022 走看看