UVA 798 - Tile Puzzle(暴力枚举)

  Tile Puzzle 

In a puzzle a rectangular surface of width w and height h is split into a collection of rectangular tiles. The tiles with the same dimensions form a similarity group. Solving the puzzle is to rebuild the surface by using the tiles from the collection. There can be many solutions. Two solutions are considered different if the tiles from at least one similarity group follow different placement patterns in the two solutions. For example, in the puzzle from figure 1 there are two groups of two similar tiles each. The tiles can be combined in eleven different ways to solve the puzzle.

Figure 1: Combining tiles to rebuild a surface

Write a program that for a given puzzle, as described above, computes the total number of different solutions of the puzzle. The puzzle surface and the tiles have integer dimensions.

Input and Output 

The program reads sets of data from a text file. Each data set, that describes a puzzle, has the format $w\ h\ n\ m_1\ w_1\ h_1\ \dots\ m_n\ w_n\ h_n$ , where  $0 < w,h \le 100$  are the dimensions of the surface to be rebuild, $0 < n \le 10$  is the number of groups of similar tiles,  m k  is the number of similar tiles in the  k -th group and  $w_k\ h_k$  are the width and the height of the tiles in the  k -th group. Input data are correct, i.e. the tiles can be always combined to rebuild the surface and all tiles must be used in the process.


For each set of data, the program writes the number of tile combinations on a separate line. The first data set in the sample below corresponds to the puzzle shown in figure 1.

Sample Input 

3 2 2
2 1 1
2 1 2

5 2 2
2 1 1
4 1 2

Sample Output 

11
56



Miguel Revilla 
2001-01-05

题意:给定一副w*h的拼图,然后有n种拼图,问用这n种拼图有几种不同的拼法。

思路:拼图问题,dfs暴力枚举。

代码:

#include <stdio.h>
#include <string.h>

const int N = 15;
const int MAXN = 105;

int w, h, n, ans, vis[MAXN][MAXN], sum;

struct P {
	int w, h, m;
} p[N];

void init() {
	memset(vis, 0, sizeof(vis));
	sum = 0;
	for (int i = 0; i < n; i ++) {
		scanf("%d%d%d", &p[i].m, &p[i].w, &p[i].h);
		sum += p[i].m;
	}
}

bool judge(int x, int y, P p, int bo) {
	if (bo) {
		if (p.h == p.w) return false;
		int t = p.w; p.w = p.h; p.h = t;
	}
	if (x + p.w > w || y + p.h > h) return false;
	for (int i = x; i < x + p.w; i++)
		for (int j = y; j < y + p.h; j++) {
			if (vis[i][j]) return false;
		}
	return true;
}

void tra(int x, int y, int bo, P p) {
	if (bo) {int t = p.w; p.w = p.h; p.h = t;}
	for (int i = x; i < x + p.w; i++)
		for (int j = y; j < y + p.h; j++)
			vis[i][j] = (vis[i][j]^1);
}

int dfs(int x, int y, int num) {
	int ans = 0;
	if (num == sum) return 1;
	if (y == h) return dfs(x + 1, 0, num);
	if (vis[x][y]) return dfs(x, y + 1, num);
	for (int i = 0; i < n; i ++) {
		if (!p[i].m) continue;
		if (judge(x, y, p[i], 0)) {
			tra(x, y, 0, p[i]); p[i].m--;
			ans += dfs(x, y + 1, num + 1);
			tra(x, y, 0, p[i]); p[i].m++;
		}
		if (judge(x, y, p[i], 1)) {
			tra(x, y, 1, p[i]); p[i].m--;
			ans += dfs(x, y + 1, num + 1);
			tra(x, y, 1, p[i]); p[i].m++;
		}
	}
	return ans;
}

int main() {
	while (~scanf("%d%d%d", &w, &h, &n)) {
		init();
		printf("%d\n", dfs(0, 0, 0));
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值