[HDU 2977]Color Squares[BFS]

题目链接: [HDU 2977]Color Squares[BFS]

题意分析:

在一个3X3的格子中,可以染上蓝红绿黄,分别得分:B、R、G、Y(B <= R <= G <= Y)。格子间染色有如下规则:

1.蓝色格子可以在任何位置上染色

2.红色格子只能在蓝色格子旁边才能染色

3.绿色格子必须周围至少有一个蓝色格子和一个红色格子才能染色

4.黄色格子必须周围至少有一个蓝色格子、一个红色格子、一个绿色格子才能染色

一个格子可以被重复染色,取最新的颜色作为格子颜色。

问:最少染多少步才能使得格子的分数之和>= W。如果不能,输出无解。

解题思路:

使用BFS枚举棋盘的状态。用一个九维数组标记状态。dp[i][j][k][l]记录棋盘中有i个蓝色、j个红色、k个绿色、l个黄色所需要的最少步骤。

每个状态,枚举下一个棋盘的状态即可。

注意细节,比如对一些状态的还原。

个人感受:

把整个棋盘存下来太机智了。九维数组威武!!反正特别喜欢这题~

这题看了题解去写,第一个版本用string来记录棋盘,结果慢死了,投机取巧失败+1。

然后是标记棋盘颜色时,忘记考虑棋盘原先的颜色了。总之,收益颇多。

状态这种东西,太神奇了。

具体代码如下:

#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<string>
#define pr(x) cout << #x << " = " << (x) << '\n';
using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 111;

bool vis[5][5][5][5][5][5][5][5][5];
int dp[10][10][10][10];
int dir[2][4] = {1, -1, 0, 0, 0, 0, 1, -1};
struct S {
    int mp[3][3];
    int step;
    int num[5];
    S(){
        memset(mp, 0, sizeof mp);
        step = 0;
        memset(num, 0, sizeof num);
    }
};

void bfs() {
    queue<S> q;
    S fst;
    q.push(fst);
    vis[0][0][0][0][0][0][0][0][0] = 1;
    while (q.size()) {
        S u = q.front(); q.pop();
        dp[u.num[1]][u.num[2]][u.num[3]][u.num[4]] = min(u.step, dp[u.num[1]][u.num[2]][u.num[3]][u.num[4]]);
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                int org = u.mp[i][j];

                // blue
                if (u.mp[i][j] != 1) {
                    ++u.step;
                    ++u.num[1];
                    --u.num[org];
                    u.mp[i][j] = 1;
                    if (!vis[u.mp[0][0]][u.mp[0][1]][u.mp[0][2]][u.mp[1][0]][u.mp[1][1]][u.mp[1][2]][u.mp[2][0]][u.mp[2][1]][u.mp[2][2]]) {
                        vis[u.mp[0][0]][u.mp[0][1]][u.mp[0][2]][u.mp[1][0]][u.mp[1][1]][u.mp[1][2]][u.mp[2][0]][u.mp[2][1]][u.mp[2][2]] = 1;
                        q.push(u);
                    }
                    u.mp[i][j] = org;
                    ++u.num[org];
                    --u.num[1];
                    --u.step;
                }

                // red
                int num1 = 0, num2 = 0, num3 = 0;
                for (int k = 0; k < 4; ++k) {
                    int nx = i + dir[0][k], ny = j + dir[1][k];
                    if (0 <= nx && nx < 3 && 0 <= ny && ny < 3) {
                        if (u.mp[nx][ny] == 1)
                            ++num1;
                    }
                }
                if (num1 && u.mp[i][j] != 2) {
                    ++u.step;
                    ++u.num[2];
                    --u.num[org];
                    u.mp[i][j] = 2;
                    if (!vis[u.mp[0][0]][u.mp[0][1]][u.mp[0][2]][u.mp[1][0]][u.mp[1][1]][u.mp[1][2]][u.mp[2][0]][u.mp[2][1]][u.mp[2][2]]) {
                        vis[u.mp[0][0]][u.mp[0][1]][u.mp[0][2]][u.mp[1][0]][u.mp[1][1]][u.mp[1][2]][u.mp[2][0]][u.mp[2][1]][u.mp[2][2]] = 1;
                        q.push(u);
                    }
                    u.mp[i][j] = org;
                    ++u.num[org];
                    --u.num[2];
                    --u.step;
                }

                // green
                num1 = 0, num2 = 0, num3 = 0;
                for (int k = 0; k < 4; ++k) {
                    int nx = i + dir[0][k], ny = j + dir[1][k];
                    if (0 <= nx && nx < 3 && 0 <= ny && ny < 3) {
                        if (u.mp[nx][ny] == 1)
                            ++num1;
                        if (u.mp[nx][ny] == 2)
                            ++num2;
                    }
                }
                if (num1 && num2 && u.mp[i][j] != 3) {
                    ++u.step;
                    ++u.num[3];
                    --u.num[org];
                    u.mp[i][j] = 3;
                    if (!vis[u.mp[0][0]][u.mp[0][1]][u.mp[0][2]][u.mp[1][0]][u.mp[1][1]][u.mp[1][2]][u.mp[2][0]][u.mp[2][1]][u.mp[2][2]]) {
                        vis[u.mp[0][0]][u.mp[0][1]][u.mp[0][2]][u.mp[1][0]][u.mp[1][1]][u.mp[1][2]][u.mp[2][0]][u.mp[2][1]][u.mp[2][2]] = 1;
                        q.push(u);
                    }
                    u.mp[i][j] = org;
                    ++u.num[org];
                    --u.num[3];
                    --u.step;
                }

                // yellow
                num1 = 0, num2 = 0, num3 = 0;
                for (int k = 0; k < 4; ++k) {
                    int nx = i + dir[0][k], ny = j + dir[1][k];
                    if (0 <= nx && nx < 3 && 0 <= ny && ny < 3) {
                        if (u.mp[nx][ny] == 1)
                            ++num1;
                        if (u.mp[nx][ny] == 2)
                            ++num2;
                        if (u.mp[nx][ny] == 3)
                            ++num3;
                    }
                }
                if (num1 && num2 && num3 && u.mp[i][j] != 4) {
                    ++u.step;
                    ++u.num[4];
                    --u.num[org];
                    u.mp[i][j] = 4;
                    if (!vis[u.mp[0][0]][u.mp[0][1]][u.mp[0][2]][u.mp[1][0]][u.mp[1][1]][u.mp[1][2]][u.mp[2][0]][u.mp[2][1]][u.mp[2][2]]) {
                        vis[u.mp[0][0]][u.mp[0][1]][u.mp[0][2]][u.mp[1][0]][u.mp[1][1]][u.mp[1][2]][u.mp[2][0]][u.mp[2][1]][u.mp[2][2]] = 1;
                        q.push(u);
                    }
                    u.mp[i][j] = org;
                    ++u.num[org];
                    --u.num[4];
                    --u.step;
                }
            }
        }
    }
}

void init() {
    memset(vis, 0, sizeof vis);
    memset(dp, 0x3f, sizeof dp);
    bfs();
}

int main()
{
    init();
    int b, r, g, y, w, kase = 0;
    while (~scanf("%d", &b) && b) {
        printf("Case %d: ", ++kase);
        scanf("%d%d%d%d", &r, &g, &y, &w);
        int ans = INF;
        for (int i = 0; i < 10; ++i) {
            for (int j = 0; j < 10; ++j) {
                for (int k = 0; k < 10; ++k) {
                    for (int l = 0; l < 10; ++l)
                        if (b*i + r*j + g*k + l*y >= w) {
                            ans = min(ans, dp[i][j][k][l]);
                        }
                }
            }
        }
        if (ans == INF) printf("Impossible\n");
        else printf("%d\n", ans);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值