DFS解法:http://www.cnblogs.com/E-star/archive/2012/08/11/2633842.html
http://poj.org/problem?id=1691
题意:
给定一个大矩形,然后给出n个需要染色的小矩形的左上角的坐标,右下角的坐标以及该矩形要染得颜色,每个颜色对应的一把刷子。问将这些小矩形染完规定的颜色之后需要最少的刷子数。
要求:只当该小矩形的上边的矩形都染完色之后,该矩形才能染色,如果同一个刷子被使用多次也要计算进来;
View Code
#include <cstdio> #include <cstring> #include <iostream> #define maxn 17 using namespace std; const int inf = 99999999; struct node { int lx,ly; int rx,ry; int col; }p[maxn]; int dp[1<<maxn][maxn]; int mp[maxn],n,state; void init() { memset(mp,0,sizeof(mp)); int i,j; for (i = 0; i < n; ++i) { for (j = 0; j < n; ++j) { if (i != j && p[i].ry == p[j].ly && !(p[j].rx < p[i].lx || p[j].lx > p[i].rx)) { mp[j] |= (1<<i);//记录j上边所有的矩形 } } } //初始化 for (i = 0; i < state; ++i) { for (j = 0; j < n; ++j) { dp[i][j] = inf; } } //初始化上边矩形个数为0的 for (i = 0; i < n; ++i) { if (mp[i] == 0) dp[1<<i][i] = 1; } } void DP() { int i,j,k; for (i = 0; i < state; ++i) { for (j = 0; j < n; ++j) { if ((i&(1<<j)) == 0 && (i&(mp[j])) == mp[j])//如果i状态里面还不存在j矩形并且j上边的矩形在i这个状态里面都染过色了 { for (k = 0; k < n; ++k) { if (i&(1<<k))//i这个状态里面存在k我们才能有他推加入j的情况 { if (p[k].col == p[j].col) dp[i + (1<<j)][j] = min(dp[i + (1<<j)][j],dp[i][k]); else dp[i + (1<<j)][j] = min(dp[i + (1<<j)][j],dp[i][k] + 1); } } } } } int Min = inf; for (i = 0; i < n; ++i) { //printf(">>%d\n",dp[state - 1][i]); if (Min > dp[state - 1][i]) Min = dp[state - 1][i]; } printf("%d\n",Min); } int main() { //freopen("d.txt","r",stdin); int t,i; scanf("%d",&t); while (t--) { scanf("%d",&n); for (i = 0; i < n; ++i) scanf("%d%d%d%d%d",&p[i].ly,&p[i].lx,&p[i].ry,&p[i].rx,&p[i].col); state = (1<<n);//记录所有状态 init(); DP(); } return 0; }