2014北京赛区现场赛B hdu 5113 Black And White

Black And White

Problem Description
In mathematics, the four color theorem, or the four color map theorem, states that, given any separation of a plane into contiguous regions, producing a figure called a map, no more than four colors are required to color the regions of the map so that no two adjacent regions have the same color.
— Wikipedia, the free encyclopedia

In this problem, you have to solve the 4-color problem. Hey, I’m just joking.

You are asked to solve a similar problem:

Color an N × M chessboard with K colors numbered from 1 to K such that no two adjacent cells have the same color (two cells are adjacent if they share an edge). The i-th color should be used in exactly c i cells.

Matt hopes you can tell him a possible coloring.
 

Input
The first line contains only one integer T (1 ≤ T ≤ 5000), which indicates the number of test cases.

For each test case, the first line contains three integers: N, M, K (0 < N, M ≤ 5, 0 < K ≤ N × M ).

The second line contains K integers c i (c i > 0), denoting the number of cells where the i-th color should be used.

It’s guaranteed that c 1 + c 2 + · · · + c K = N × M .
 

Output
For each test case, the first line contains “Case #x:”, where x is the case number (starting from 1). 

In the second line, output “NO” if there is no coloring satisfying the requirements. Otherwise, output “YES” in one line. Each of the following N lines contains M numbers seperated by single whitespace, denoting the color of the cells.

If there are multiple solutions, output any of them.
 

Sample Input
  
  
4 1 5 2 4 1 3 3 4 1 2 2 4 2 3 3 2 2 2 3 2 3 2 2 2
 

Sample Output
  
  
Case #1: NO Case #2: YES 4 3 4 2 1 2 4 3 4 Case #3: YES 1 2 3 2 3 1 Case #4: YES 1 2 2 3 3 1
 

题意就是 给定n*m的网络以及k种颜色的棋子  每种颜色的棋子有c[i]个

现在要将这些棋子按要求摆放  具有共同边的即相邻的两个网格不能摆放相同颜色的棋子

问这样的摆放情况是否存在 存在就输出任意一种情况

分析可以知道 如果当前某种棋子的个数大于剩下网格的二分之一 摆放的情况是不存在的

根据这个条件可以对程序进行剪枝优化!!!!

剩下的就是暴搜 在要一个新的点进行摆放棋子时  要判断这个棋子四个方向上的棋子跟它是否是同一种颜色的

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>

#define eps 1e-8
#define op operator
#define MOD  10009
#define MAXN  100100
#define INF 0x7fffffff
#define MEM(a,x)    memset(a,x,sizeof a)
#define ll __int64

using namespace std;

int n,m,k;
//int c[30];
int flag;
int mp[6][6];
int sum;
int dir[4][2]={{-1,0},{0,-1},{0,1},{1,0}};

struct node
{
    int num;//颜色值
    int cnt;//当前个数
    bool operator<(const node p)const
    {
        return cnt<p.cnt;
    }
};
node no[30];

void dfs(int x,int y,int col)
{
    if(sum==0)
    {
        flag=1;
        puts("YES");
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(j==0)
                    printf("%d",mp[i][j]);
                else printf(" %d",mp[i][j]);
            }
            puts("");
        }
        return;
    }
    if(flag)  return;
    for(int i=1;i<=k;i++)
    {
        if(no[i].cnt>(sum+1)/2)
            return;
    }
    for(int i=0;i<4;i++)
    {
        int xx=x+dir[i][0]; int yy=y+dir[i][1];
        if(xx<0||xx>=n||yy<0||yy>=m||mp[xx][yy])
            continue;
        for(int p=1;p<=k;p++)
        {
            if(!no[p].cnt)
                continue;
            if(no[p].num==col)
                continue;
            int f=0;
            for(int j=0;j<4;j++)
            {

                int xxx=xx+dir[j][0]; int yyy=yy+dir[j][1];
//                cout<<"no[p].num:"<<no[p].num<<" xxx:"<<xxx<<" yyy:"<<yyy<<" mp:"<<mp[xxx][yyy]<<endl;
                if(xxx<0||xxx>=n||yyy<0||yyy>=m)
                    continue;
                if(mp[xxx][yyy]==no[p].num)
                {
                    f=1; break;
                }
            }
            if(f)
                continue;
            mp[xx][yy]=no[p].num;
            no[p].cnt--;
            sum--;
            dfs(xx,yy,no[p].num);
            if(flag)
                return;
            mp[xx][yy]=0;
            no[p].cnt++;
            sum++;
        }

    }
}

int main()
{
//freopen("ceshi.txt","r",stdin);
    int tc;
    scanf("%d",&tc);
    int cs=1;
    while(tc--)
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=k;i++)
        {
            scanf("%d",&no[i].cnt);
            no[i].num=i;
        }
        sort(no+1,no+1+k);
        sum=n*m;
        printf("Case #%d:\n",cs++);
        if(no[k].cnt>(sum+1)/2)
        {
            puts("NO");
            continue;
        }
        flag=0;
        MEM(mp,0);
        for(int i=1;i<=k;i++)
        {
            MEM(mp,0);
            no[i].cnt--;
            mp[0][0]=no[i].num;
            sum--;
            dfs(0,0,no[i].num);
            if(flag)
                break;
            sum++;
            mp[0][0]=0;
            no[i].cnt++;
        }
        if(!flag)
            puts("NO");
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值