HDOJ 5113 Black And White黑與白

DFS深搜的剪枝。

題目大意,輸入一個t(1 <= t < =5000)有t組測試數據,每一組測試數據,第一行輸入n,m,k,(0 <=n , m <= 5 , 0 <= k <= 25)第二行 然後k個數,在n * m的矩陣中用着k中顏色填充每個格子,dii中顏色有有k[i]個,共n * m個顏色(注意是k種顏色,共有n * m個顏色),去填充着n*m個格子,每個格子的上向左右填充的顏色不能相同,要求找到一組這樣的解,若存在一種解,則輸出YES,然後輸出每個單元填充的顏色,否則輸出NO。若存在多種可行解,輸出任意一種即可。

首先你肯定會想到dfs,去嘗試用剩下的顏色填充某個格子,若將所有格子都填充完了,並且每個格子的上下左右都不相同,則這是可行解,否則就沒有解。但是這一定會超時,你得有優秀的剪枝。最重要的剪枝:當前狀態還剩下cnt個格子沒有填,某種顏色剩下x個,若某個x大於格子數的一半,即x > (cnt + 1) / 2,則此次嘗試一定是不行的。具體請讀者畫圖嘗試一下。

下面貼出代碼,供大家參考。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n, m, k, arr[26], maze[6][6], color[26];
int dir[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};
//填x,y這個點,maze裏還有cnt個格子未填
bool dfs(int x, int y, int cnt) 
{
    //如果填完了,就true
    if(!cnt) return true; 
    //如果x,y超出範圍就返回false
    if(x <= 0 || x > n || y <= 0 || y > m) return false;
    //剪枝:如果剩餘的格子數的一半大於某顏色,則這種做法就不行,返回false
    for(int i = 1; i <= k; ++i) 
    {
        if((cnt + 1) / 2 < arr[i]) 
            return false;
    }
    bool vised[26];
    memset(vised, false, sizeof vised);
    //vised記錄當前x,y點的上下左右填的顏色,x,y不能填
    for(int i = 0; i < 4; ++i)
    {
        int dx = x + dir[i][0], dy = y + dir[i][1];
        if(dx > 0 && dx <= n && dy > 0 && dy <= m)
            vised[maze[dx][dy]] = true;
    }
    for(int i = 1; i <= k; ++i)//嘗試i顏色
    {
        if(arr[i] > 0 && !vised[i])
        {
            arr[i]--;
            maze[x][y] = i; 
            for(int j = 0; j < 4; ++j)
            {
                int dx = x + dir[j][0], dy = y + dir[j][1];
                if(maze[dx][dy] == 0 && dfs(dx, dy, cnt - 1))
                    return true;
            }
            arr[i]++;
            maze[x][y] = 0;
        }
    }
    return false;
}
int main()
{
    int t;
    scanf("%d", &t);
    for(int I = 1; I <= t; ++I)
    {
        memset(maze, 0, sizeof maze);
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1; i <= k; ++i)
        {
            scanf("%d", &arr[i]);
            color[i] = arr[i];
        }
        printf("Case #%d:\n", I);
        if(dfs(1, 1, m * n))
        {
            puts("YES");
            for(int i = 1; i <= n; ++i)
            {
                for(int j = 1; j <= m; ++j)
                    printf("%d%c", maze[i][j], j < m? ' ': '\n');
            }
        }
        else 
            puts("NO");
    }
    return 0;
}

發佈了24 篇原創文章 · 獲贊 6 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章