CSU2073: Tile Cut

原创 2018年04月15日 20:23:51

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.

Sample Input

WIIW
NNNN
IINN
WWWI

NINWN
INIWI
WWWIW
NNNNN
IWINN

Sample Output

5
5

Hint

Source

pacnw2012

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

题解:W只能对上下左右的I连一条出边,I也只能对上下左右的N连一条出边,很明显是一道最大流的问题。我们建立一个源点S,S对每个W连一条容量为1的边;每个W连一条到上下左右I的边;每个I连一条到上下最后N的边;每个N连一条到汇点T的边;只需要求S到T的最大流即可。

注意,以上题解有误!!!题目要求每个点只能访问一次,而以上题解可能会导致一个点被访问多次!如两个W连一个I,那个I连两个N。。。。。因此,我们需要保证每个点只能被访问一次,这种方法叫拆点法!把每个点拆成一条容量为1的边,如此答案即为正确。

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;
}

简便用于寻打cutoff工具-----x-tile

  • 2016年10月09日 22:41
  • 2.18MB
  • 下载

Wet Tiles CSU Contest2073 - 湖南多校对抗赛(2015.04.06) I

Contest2073 - 湖南多校对抗赛(2015.04.06) 1569 Problem I Wet Tiles For each house, display the total numb...
  • WeirdoMaybe
  • WeirdoMaybe
  • 2015-04-07 00:47:46
  • 272

LA 6234 Tile Cut dinic

蛋疼的输入。。。。。
  • EOD_realize
  • EOD_realize
  • 2014-11-22 15:53:22
  • 464

Numpy中 tile函数的用法

titl函数: a=arange(1,3)#a的结果是:array([1,2])1,当 tile(a,1) 时:tile(a,1)#结果是array([1,2]) tile(a,2)#结果...
  • baiyu9821179
  • baiyu9821179
  • 2016-11-27 15:46:47
  • 3989

Python中numpy模块的tile()方法简单说明

函数形式: tile(A,rep) 功能:重复A的各个维度 参数类型: - A: Array类的都可以 - rep:A沿着各个维度重复的次数举例:tile([1,2],2)输出[1,2,1...
  • wy250229163
  • wy250229163
  • 2016-09-06 20:23:19
  • 6332

【python系列】numpy中的tile函数

tile函数         在看机器学习实战这本书时,遇到numpy.tile(A,B)函数,愣是没看懂怎么回事,装了numpy模块后,实验了几把,原来是这样子: 重复A,B次,这里的B...
  • piaoxuefengqi
  • piaoxuefengqi
  • 2014-03-17 15:09:41
  • 34312

[Python]numpy中tile函数的用法

1.函数的定义与说明 tile函数是模板numpy.lib.shape_base中的函数。 函数的形式是tile(A,reps) 函数参数说明中提到A和reps都是array_like的,什么是arr...
  • sinat_31601333
  • sinat_31601333
  • 2016-10-09 16:07:10
  • 2230

numpy.tile()

numpy.tile()是个什么函数呢,说白了,就是把数组沿各个方向复制 比如 a = np.array([0,1,2]),    np.tile(a,(2,1))就是把a先沿x轴(就这样称呼吧)复...
  • qq_18433441
  • qq_18433441
  • 2017-02-06 21:50:19
  • 5084

Numpy中的tile方法

1、shape 2、tile 原型:numpy.tile(A,reps) 重复数组A构建新数组,reps决定A重复的次数。 如果reps的长度为d,那么新数组的维度为max(d,A.ndim)。下面分...
  • xiahei_d
  • xiahei_d
  • 2016-10-07 14:30:25
  • 2030

tile函数的使用

【python】tile函数简单介绍 格式:tile(A,reps) * A:array_like * 输入的array * reps:array_like * A沿各个维度重复的次...
  • Alis_xt
  • Alis_xt
  • 2016-11-10 17:32:27
  • 1030
收藏助手
不良信息举报
您举报文章:CSU2073: Tile Cut
举报原因:
原因补充:

(最多只允许输入30个字)