pku 1691 painting a board dfs+回溯 解题报告

 

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;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值