题目链接:uva 798 - Tile Puzzle
题目大意:给出w,h和n,表示有n种拼图,给出n种拼图的个数mi,宽wi,高hi,问说用这些拼图可以用多少中不同的方法拼凑出w*h。
解题思路:回溯法,注意拼图的宽如果不等于长的话,是可以旋转的。
#include <stdio.h> #include <string.h> const int N = 20; const int M = 105; int n, c, r, ans; int w[N], h[N], m[N], g[M][M]; void init() { ans = 0; memset(g, 0, sizeof(g)); for (int i = 0; i < n; i++) scanf("%d%d%d", &m[i], &w[i], &h[i]); } bool judge(int x, int y, int p, int q) { if (x + p > r || y + q > c) return false; for (int i = 0; i < p; i++) { for (int j = 0; j < q; j++) { if (g[x + i][y + j]) return false; } } return true; } void set(int x, int y, int p, int q, int d) { for (int i = 0; i < p; i++) { for (int j = 0; j < q; j++) g[x + i][y + j] = d; } } void dfs(int x, int y) { if (y >= c) { x += 1; y = 0; } if (x >= r) { ans++; return; } if (!g[x][y]) { for (int i = 0; i < n; i++) if (m[i]) { if (judge(x, y, h[i], w[i])) { set(x, y, h[i], w[i], 1); m[i]--; dfs(x, y + 1); set(x, y, h[i], w[i], 0); m[i]++; } if (judge(x, y, w[i], h[i]) && h[i] != w[i]) { set(x, y, w[i], h[i], 1); m[i]--; dfs(x, y + 1); set(x, y, w[i], h[i], 0); m[i]++; } } } else dfs(x, y + 1); } int main () { while (scanf("%d%d%d", &c, &r, &n) == 3) { init(); dfs(0, 0); printf("%d\n", ans); } return 0; }