pku 1691 painting a board 解题报告
算法:
先将数据转化为有向图,然后dfs+回溯.
如sample中的数据可以变为以下的有向图:
然后利用深度搜索+回溯,求出最优值.
AC代码:
#include <stdio.h>
#include <string.h>
#define M 20
#define inf 1000000
int n;
int map[M][M], degree[M], r[M], color_num;
void init()
{
int i, j;
int a[M], b[M], c[M], d[M];
scanf("%d", &n);
color_num = 0;
for (i = 1; i <= n; i++)
{
scanf("%d%d%d%d%d", &a[i], &b[i], &c[i], &d[i], &r[i]);
if (color_num > r[i])
{
color_num = r[i];
}
}
//建立有向图
memset(map, 0, sizeof(map));
memset(degree, 0, sizeof(degree));
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
if (i != j && c[i] == a[j] && a[i] < a[j] && !((d[i] <= b[j]) || (d[j] <= b[i])))
{
map[i][j] = 1;
degree[j]++;
}
}
}
/*for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
printf("%d ", map[i][j]);
}
printf("/n");
}
printf("/n");*/
}
int visit[M];
int solve(int color, int count)
{
int ans = inf;
int i, j, k;
for (i = 1; i <= n; i++)
{
if (degree[i] == 0 && visit[i] == 0)
{
visit[i] = 1;
//颜色不一样,那么count就相加
if (r[i] != color)
{
count++;
}
//i相应的儿子j的入度-1
for (j = 1; j <= n; j++)
{
if (map[i][j])
{
degree[j]--;
}
}
//搜索
k = solve(r[i], count);
//取最优值
if (k < ans)
{
ans = k;
}
//回溯
for (j = 1; j <= n; j++)
{
if (map[i][j])
{
degree[j]++;
}
}
visit[i] = 0;
if (r[i] != color)
{
count--;
}
}
}
if (ans == inf)
{
ans = count;
}
return ans;
}
int main()
{
//freopen("1.txt", "r", stdin);
int test;
scanf("%d", &test);
while (test--)
{
init();
memset(visit, 0, sizeof(visit));
printf("%d/n", solve(-1, 0));
}
return 0;
}