# CSU2073: Tile Cut

## Description

When Frodo, Sam, Merry, and Pippin are at the Green Dragon Inn drinking ale, they like to play a little game with parchment and pen to decide who buys the next round. The game works as follows: Given an m × n rectangular tile with each square marked with one of the incantations W, I, and N, find the maximal number of triominoes that can be cut from this tile such that the triomino has W and N on the ends and I in the middle (that is, it spells WIN in some order). Of course the only possible triominoes are the one with three squares in a straight line and the two ell-shaped ones. The Hobbit that is able to find the maximum number wins and chooses who buys the next round. Your job is to find the maximal number. Side note: Sam and Pippin tend to buy the most rounds of ale when they play this game, so they are lobbying to change the game to Rock, Parchment, Sword (RPS)!

## Input

Each input file will contain multiple test cases. Each test case consists of an m × n rectangular grid (where 1 ≤ m, n ≤ 30) containing only the letters W, I, and N. Test cases will be separated by a blank line. Input will be terminated by end-of-file.

## Output

For each input test case, print a line containing a single integer indicating the maximum total number of tiles that can be formed.

WIIW
NNNN
IINN
WWWI

NINWN
INIWI
WWWIW
NNNNN
IWINN

5
5

pacnw2012

## 题意：有m行n列的输入，每个输入以空行结束。对于每个输入模块，求最多能删除几个连在一起的WIN（可连接的要求为上下左右相邻），输出最大操作数。

AC代码

#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <stdio.h>

using namespace std;

const int maxn = 3333, INF = 1000000000;
int n, m, dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};

char gg[maxn / 10][maxn / 10];

struct Edge{
int from, to, cap, flow;
Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f){}
};

struct EdmondsKarp{
int n, m;
vector<Edge> edges;
vector<int> G[maxn];
int a[maxn];
int p[maxn];

void init(int n){
for(int i = 0; i < n; i++)
G[i].clear();
edges.clear();
}

void AddEdge(int from, int to, int cap){
edges.push_back(Edge(from, to, cap, 0));
edges.push_back(Edge(to, from, 0, 0));
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}

int Maxflow(int s, int t){
int flow = 0;
for(;;){
memset(a, 0, sizeof(a));
queue<int> Q;
Q.push(s);
a[s] = INF;
while(!Q.empty()){
int x = Q.front();
Q.pop();
for(int i = 0; i < G[x].size(); i++){
Edge &e = edges[G[x][i]];
if(!a[e.to] && e.cap > e.flow){
p[e.to] = G[x][i];
a[e.to] = min(a[x], e.cap - e.flow);
Q.push(e.to);
}
}
if(a[t])
break;
}
if(!a[t])
break;
for(int u = t; u != s; u = edges[p[u]].from){
edges[p[u]].flow += a[t];
edges[p[u]^1].flow -= a[t];
}
flow += a[t];
}
return flow;
}
};

bool check(int x, int y){
if(x >= 0 && x < n && y >= 0 && y < m)
return true;
return false;
}

void solve(){
EdmondsKarp ee;
m = strlen(gg[0]);
ee.n = n;
ee.init(n);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
if(gg[i][j] == 'W'){
ee.AddEdge(i * m + j, i * m + j + 1000, 1);
ee.AddEdge(n * m, i * m + j, 1);
for(int k = 0; k < 4; k++){
int x = i + dir[k][0];
int y = j + dir[k][1];
if(check(x, y) && gg[x][y] == 'I')
ee.AddEdge(i * m + j + 1000, x * m + y, 1);
}
}
if(gg[i][j] == 'I'){
ee.AddEdge(i * m + j, i * m + j + 1000, 1);
for(int k = 0; k < 4; k++){
int x = i + dir[k][0];
int y = j + dir[k][1];
if(check(x, y) && gg[x][y] == 'N'){
ee.AddEdge(i * m + j + 1000, x * m + y, 1);
ee.AddEdge(x * m + y + 1000, n * m + 1, 1);
}
}
}
if(gg[i][j] == 'N')
ee.AddEdge(i * m + j, i * m + j + 1000, 1);
}
int ans = ee.Maxflow(n * m, n * m + 1);
printf("%d\n", ans);
}

int main(){
//    freopen("in.txt", "r", stdin);
int n1 = 0;
while(gets(gg[n1]) != NULL){
if(strlen(gg[n1]) == 0){
n = n1;
solve();
n1 = 0;
}
else
n1++;
}
n = n1;
solve();
return 0;
}