提升coding能力------搜索专题(9)-----poj 1691

pku 1691 Painting A Board
题目地址:
http://acm.pku.edu.cn/JudgeOnline/problem?id=1691

题目大意:

就是给你一块大矩形,里面由一块块小矩形拼凑而成,通过给出小矩形的左上端点和右下端点的坐标来给出小矩形。

每块小矩形都有一个颜色属性(用一个数字来代表),问最少需要换多少次颜料就可以把所有矩形都涂上符合其自身属性的颜色。

涂色的规则:

                  一块矩形被涂色之前,还必须保证一个条件———与这块矩形相邻且在这块矩形的上面的所有矩形必须都被涂色了,这个条件满足后,这块矩形才能被涂色。

 

具体分析:

假设现在有:

            矩形A,矩形B,矩形C(假设三个矩形的相邻情况是A与B相邻,B与C相邻)

颜色      1             2          1

我可以先拿颜色1对矩形A涂色,然后对矩形C涂色,再换颜料2,然后对矩形B涂色,一共换颜料换了2次。

我也可以拿颜色1对矩形A涂色,然后换颜料2对矩形B涂色,再换成颜料1对矩形C涂色,一共颜料换了3次。

其实就是一个DFS,用当前手上的颜料,从头到尾进行涂色,

如果一个矩形满足了 "当前颜料 == 该矩形颜色” &&“与该矩形相邻的上方矩形都被涂色”的话,

那么此时有两种选择,我可以选择涂该矩形,然后继续DFS。

                                    也可以选择跳过,然后继续DFS。

如果上面两个条件无法同时满足的话,那么就只剩下一种选项,也就是跳过该矩形,然后继续DFS。

AC代码:
 

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<queue>
#include<vector>
using namespace std;
#define N 100
struct Node
{
    int l_x ,l_y;
    int r_x , r_y;
    int num;
};
int Mark[30], n,minn;
Node Gra[20];
int check(int  pos) //判断pos上面的图形是否已经都被染色了
{

  for(int i = 0 ;i < n ;i++ )
  {

     if(Gra[i].r_x == Gra[pos].l_x && Gra[i].l_y <= Gra[pos].r_y  )
     {
        if(!Mark[i])
            return 0;

     }
  }

    return  1;

}
void DFS(int Color, int cnt,int ans)
{
    if(cnt == n )
    {
        if(ans <= minn)
            minn = ans;
       // if(minn == 4)
            //cout << "ok" << endl;
        return ;
    }

     for( int i = 0 ;i < n ; i++)
     {
         if( !Mark[i] && check(i) )
         {
             if( Gra[i].num == Color )
             {
                Mark[i] = 1;
                DFS( Color, cnt + 1 ,ans );
                Mark[i] = 0;
             }
             else if( Gra[i].num != Color )
             {
                Mark[i] = 1;
                DFS(Gra[i].num, cnt + 1, ans + 1);
                Mark[i] = 0;
             }

         }
     }

     return ;
}
int  main()
{
    int cnt ;
    cin >> cnt;

    while( cnt-- )
    {
        cin >> n;
        //memset(vis,0,sizeof(vis));
        memset(Mark,0,sizeof(Mark));
        for(int i = 0 ;i < n ;i++)
        {

           cin >> Gra[i].l_x >> Gra[i].l_y >> Gra[i].r_x >> Gra[i].r_y >> Gra[i].num;
           //cout << Gra[i].l_x << Gra[i].l_y << Gra[i].r_x << Gra[i].r_y << Gra[i].num << endl;
        }




        minn = 999999;
        DFS(-1,0,0);
        cout << minn << endl;




    }
    return 0;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值