HDU - 5965 扫雷(dp[好理解,但不那么优的题解])

本文深入探讨了扫雷游戏中的算法挑战,特别是针对特定游戏布局的解决方案。通过动态规划和状态压缩技巧,文章详细解释了如何高效计算合法的埋雷方案数,提供了完整的代码实现,适合对算法和游戏开发感兴趣的读者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

扫雷

Problem Description
扫雷游戏是晨晨和小璐特别喜欢的智力游戏,她俩最近沉迷其中无法自拔。
该游戏的界面是一个矩阵,矩阵中有些格子中有一个地雷,其余格子中没有地雷。 游戏中,格子可能处于己知和未知的状态。如果一个己知的格子中没有地雷,那么该 格子上会写有一个一位数,表示与这个格子八连通相邻的格子中地雷总的数量。
现在,晨晨和小璐在一个3行N列(均从1开始用连续正整数编号)的矩阵中进 行游戏,在这个矩阵中,第2行的格子全部是己知的,并且其中均没有地雷;而另外 两行中是未知的,并且其中的地雷总数量也是未知的。
晨晨和小璐想知道,第1行和第3行有多少种合法的埋放地雷的方案。

Input
包含多组测试数据,第一行一个正整数T,表示数据组数。
每组数据由一行仅由数字组成的长度为N的非空字符串组成,表示矩阵有3行N 列,字符串的第i个数字字符表示矩阵中第2行第i个格子中的数字。
保证字符串长度N <= 10000,数据组数<= 100。

Output
每行仅一个数字,表示安放地雷的方案数mod100,000,007的结果。

Sample Input
2
22
000

Sample Output
6
1

中文题意,不概述

思路: 很容易想到的是四维的 dpdpdp,利用状态压缩表示 0,1,2,30,1,2,30,1,2,3表示这一列的状态,分别表示 00,01,10,1100,01,10,1100,01,10,11

dp[i][j][k][l]dp[i][j][k][l]dp[i][j][k][l] 表示当前在第 iii 列,第 i−1i - 1i1 列的状态为 jjj,第 iii 列的状态为 kkk ,第 i+1i + 1i+1 列的状态为 lll

那么这样子的复杂度是 10000 * 4 * 4 * 4 * t,而时限是 1ms1ms1ms

这里可以优化一下,复杂度 10000 * 3 * 3 * 3 * t, dp[i][j][k][l]dp[i][j][k][l]dp[i][j][k][l] 表示当前在 第 iii 列,第 i−1i - 1i1 列雷的个数为 jjj,第 iii 列雷的个数为 kkk,第 i+1i + 1i+1 列雷的个数为 lll,那么显然有状态转移方程
if(k+l+m==str[i]−′0′)  dp[i][k][l][m]=(dp[i−1][0][k][l]+dp[i−1][1][k][l]+dp[i−1][2][k][l])∗(m==1?2:1)if(k + l + m == str[i] - '0')\ \ dp[i][k][l][m] = (dp[i - 1][0][k][l] + dp[i - 1][1][k][l] + dp[i - 1][2][k][l]) * (m == 1 ? 2 : 1)if(k+l+m==str[i]0)  dp[i][k][l][m]=(dp[i1][0][k][l]+dp[i1][1][k][l]+dp[i1][2][k][l])(m==1?2:1)   // m==1m == 1m==1 时有两种 01 与 10

Code:

#include<bits/stdc++.h>
#define debug(x) cerr << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair<int,int>
#define clr(a,b) memset((a),b,sizeof(a))
#define rep(i,a,b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define ull unsigned LL
#define ls i << 1
#define rs (i << 1) + 1
#define fi first
#define se second
#define ptch putchar
#define CLR(a) while(!(a).empty()) a.pop()

using namespace std;
inline LL read() {
    LL s = 0,w = 1;
    char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-')
            w = -1;
        ch = getchar();
    }
    while(isdigit(ch))
        s = s * 10 + ch - '0',ch = getchar();
    return s * w;
}
inline void write(LL x) {
    if(x < 0)
        putchar('-'), x = -x;
    if(x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
#ifndef ONLINE_JUDGE
clock_t prostart = clock();
#endif

const int mod = 1e8 + 7;
const int maxn = 1e4 + 70;
int dp[maxn][3][3][3]; /// i hang, (i - 1,i,i + 1) zhuangtai
int Num[4] = {0,1,1,2};
char str[maxn];

int main() {
#ifndef ONLINE_JUDGE
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
#endif

    int t = read();
    while(t --) {
        clr(dp,0);
        scanf("%s",str + 1);
        int len = strlen(str + 1);
        for(int j = 0; j < 4; ++ j)
            for(int k = 0; k < 4; ++ k)
                if(Num[j] + Num[k] == str[1] - '0')
                    ++ dp[1][0][Num[j]][Num[k]];
        for(int i = 2; i <= len; ++ i) {
            for(int k = 0; k < 3; ++ k) {
                if(k > str[i] - '0') break;
                for(int l = 0; l < 3; ++ l) {
                    if(k + l > str[i] - '0') break;
                    for(int m = 0; m < (i == len ? 1 : 3); ++ m) {
                        if(k + l + m == str[i] - '0'){
                            dp[i][k][l][m] = (dp[i - 1][0][k][l] + dp[i - 1][1][k][l] + dp[i - 1][2][k][l]) * (m == 1 ? 2 : 1) % mod;
                        }
                    }
                }
            }
        }
        LL ans = 0;
        for(int i = 0; i < 3; ++ i)
            for(int j = 0; j < 3; ++ j)
                ans = (ans + dp[len][i][j][0]) % mod;
        write(ans);
        ptch('\n');
    }

#ifndef ONLINE_JUDGE
    cout << "time: " << 1.0 * (clock() - prostart) / CLOCKS_PER_SEC << " s" << endl;
#endif
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值