题目大意:给一个包含N个矩形的板子上色,每个矩形的颜色已经确定,给一个矩形上色时,必须满足它上方的所有矩形已经上色结束,一个刷子只能用一次且涂满整个矩形,问最少需要多少个刷子
输入:case个数M (1 <= M <= 10)
第i个case的矩形个数N(1<=N<=15)
N个矩形的描述(左上角坐标y x 右下角坐标y x(坐标0~99横坐标x纵坐标y) 颜色代码(代码1~20))(每个占一行)
输出:需要的最小刷子个数
分析:dfs+dp
先输入建图,存储好矩形i上方相邻的矩形j的编号,然后依次对矩形进行dfs,判断它上方是否已涂,若满足,则涂这个矩形,涂时判断刷子要不要+1,然后继续dfs下一个矩形
代码:转载自http://blog.csdn.net/tsaid/article/details/6841823
- #include <iostream>
- using namespace std;
- #define N 16
- int m, n, ans;
- int up[N][N], mark[N]; //up[i][j]表示矩形i上方相邻的第j块(j从1起)矩形的编号。mark用来记录某一个矩形是否已经被涂色
- struct Rectangle
- {
- int x1, x2, y1, y2, color;
- } rec[N];
- bool check ( int i, int j )
- {
- if ( rec[i].y2 != rec[j].y1 ) return false;//判断是否直接相邻
- if ( rec[i].x2 <= rec[j].x1 ) return false;//判断i的最右侧是否在j的最左侧的左边
- if ( rec[i].x1 >= rec[j].x2 ) return false;//判断i的最左侧是否在j的最右侧的右边
- return true;
- }
- void build_map()
- {
- for ( int i = 1; i <= n; i++ )
- {
- for ( int j = 1; j <= n; j++ )
- if ( check(i,j) )
- up[j][++up[j][0]] = i;//i在j上方相邻
- }
- }
- void dfs ( int pick, int color, int cnt ) //刷子个数 颜色代码 矩形个数
- {
- if ( pick >= ans )
- return;
- if ( cnt == n )
- {
- ans = pick;
- return;
- }
- int i, j, flag;
- for ( i = 1; i <= n; i++ )
- {
- if ( mark[i] ) continue; // 若矩形i已经涂色,直接进入下次循环
- flag = 1;
- for ( j = 1; j <= up[i][0]; j++ )
- if ( ! mark[ up[i][j] ] ) // 若i上面的矩形中有没被涂色的,则flag = false
- {
- flag = 0; break;
- }
- if ( flag )
- {
- mark[i] = 1; // 标记i已经被涂色
- if ( rec[i].color == color )
- dfs ( pick, color, cnt+1);
- else
- dfs ( pick+1, rec[i].color, cnt+1);
- mark[i] = 0;
- }
- }
- }
- int main()
- {
- cin >> m;
- while ( m-- )
- {
- cin >> n;
- for ( int i = 1; i <= n; i++ )
- cin >> rec[i].y1 >> rec[i].x1 >> rec[i].y2 >> rec[i].x2 >> rec[i].color;
- memset(up,0,sizeof(up));
- memset(mark,0,sizeof(mark));
- ans = 999999999;
- build_map();
- dfs ( 0, 0, 0 );
- cout << ans << endl;
- }
- return 0;
- }