UVa 639 - Don't Get Rooked

题目:在n*n的方格里,放入几个喷火器,他们会攻击同行、同列的点,问做多能放多少个。

分析:图论,搜索,二分图匹配。本题可以利用搜索求解,这里我使用的是二分图匹配。

建图,把原图每行每列的不同的连续区间分别看成一个新图中的点xi与yj;

则边<xi,yj>表示原图中对应位置的点,原图中可以互相攻击的点就对应到新图中相同的xi与yj;

则新图中的二分图最大匹配即为,原图中不能相互攻击的最大摆放数量。

说明:图论关键就是建图。

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

using namespace std;

char maps[5][5];
int  g[17][17];
int  line[5][5],row[5][5];
int  used[17],link[17];

int dfs(int s, int n)
{
	for (int i = 0 ; i <= n ; ++ i)
    	if (g[s][i] && !used[i]) {
    		used[i] = 1;
        	if (link[i] == -1 || dfs(link[i], n)) {
            	link[i] = s;
            	return 1;
			}
    	}
    return 0;
}

int main()
{
	int n,x,y;
	while (~scanf("%d",&n) && n) {
		for (int i = 0 ; i < n ; ++ i)
			scanf("%s",maps[i]);

		memset(line, -1, sizeof(line));
		memset(row, -1, sizeof(row));
		int line_count = -1,row_count = -1;
		for (int i = 0 ; i < n ; ++ i)
		for (int j = 0 ; j < n ; ++ j) {
			if (j == 0 || maps[i][j] != '.')
				line_count ++;
			if (maps[i][j] == '.')
				line[i][j] = line_count;
			if (j == 0 || maps[j][i] != '.')
				row_count ++;
			if (maps[j][i] == '.')
				row[j][i] = row_count;
		}

		memset(g, 0, sizeof(g));
		for (int i = 0 ; i < n ; ++ i)
		for (int j = 0 ; j < n ; ++ j)
			if (maps[i][j] == '.')
				g[line[i][j]][row[i][j]] = 1;

		int sum = 0;
    	memset(link, -1 ,sizeof(link));
	    for(int i = 0 ; i <= line_count ; ++ i) {
		    memset(used, 0, sizeof(used));
		    sum += dfs(i, row_count);
		}

    	printf("%d\n",sum);
	}
	return 0;
}

UVa 639 - Don't Get Rooked

时间: 2024-12-21 18:10:57

UVa 639 - Don't Get Rooked的相关文章

uva 639 Don&#39;t Get Rooked (暴力回溯 )

uva 639 Don't Get Rooked In chess, the rook is a piece that can move any number of squares vertically or horizontally. In this problem we will consider small chess boards (at most 44) that can also contain walls through which rooks cannot move. The g

uva 639 Don&#39;t Get Rooked ( 回溯 )

这道题确实是标准的回溯,果然还是早上比较清醒一些,昨天晚上想了好长一会儿都没有想起来,早上一会的功夫就A 了,估计也有昨天晚上的帮助...总感觉不想写太多私人的东西在这上面,因为这个是每个人都可以无条件访问的... 思路: 由于数据比较小,可以把每个元素都遍历一遍,回溯选择,最多4*4,还是很小的,我交的才1ms,1A.. 贴代码: #include<stdio.h> #include<string.h> #include<stdlib.h> int map[10][1

Don&#39;t Get Rooked UVA 639(八皇后问题变形)

说说: 这道题目类似于八皇后问题.有n*n的正方形棋盘,且n<=4.例如在n=4时,有下图所示的棋盘,其中每两个棋子不能放在同一行或者同一列,除非有围墙(黑色的格子)将它们隔开.求给定的棋盘,能放下的最多的棋子数目. 分析: 在八皇后问题中,我们对整个棋盘分成八行考虑的,每行插入一个棋子.所以对于这道题目解决方案也类似,同样是一行一行插入.但是与八皇后问题不同的是,本题中棋盘一行可能插入多个棋子,也可能没有棋子.所以在递归函数中,不仅要给出所要处理的行的信息,也要给出所要处理的列的信息,其实就是

UVa 639 放车问题

题意:给定一个 n x n 的棋盘,在上面放置车.其中.号表示可放置,X表示墙.在同一行或同一列的两个车,如果它们之间没有X墙挡着,则是不合法的放置.给定一棋盘,最多可以放置车的数量. 思路:枚举所有的格子,看是否可以在此放置.每次放一个车后,修改棋盘的横行.竖列直到X的位置为1,即不可放置.因为要修改棋盘,所以需拷贝一个过来,修改拷贝的.还有一些注意的,如注释,总感觉写得不是很简洁. 还有就是,二维数组做参数时,可以用 char b[][5],  或者 char (*b)[5].但不能是 ch

UVA - 639

  Don't Get Rooked  In chess, the rook is a piece that can move any number of squares vertically or horizontally. In this problem we will consider small chess boards (at most 44) that can also contain walls through which rooks cannot move. The goal i

UVA题目分类

题目 Volume 0. Getting Started 开始10055 - Hashmat the Brave Warrior 10071 - Back to High School Physics 10300 - Ecological Premium 458 - The Decoder 494 - Kindergarten Counting Game 414 - Machined Surfaces 490 - Rotating Sentences 445 - Marvelous Mazes

UVA Don&#39;t Get Rooked

题目如下:  Don't Get Rooked  In chess, the rook is a piece that can move any number of squaresvertically or horizontally. In this problem we will consider smallchess boards (at most 44) that can also contain walls through whichrooks cannot move. The goal

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

UVA 10341 Solve It

Problem F Solve It Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB Solve the equation: p*e-x + q*sin(x) + r*cos(x) + s*tan(x) + t*x2 + u = 0 where 0 <= x <= 1. Input Input consists of multiple test cases and te