HDOJ 5965 扫雷 【DP】
来源:互联网 发布:php app接口开发步骤 编辑:程序博客网 时间:2024/06/05 00:12
扫雷
TimeLimit: 2000/1000 MS (Java/Others) Memory Limit:65536/65536 K (Java/Others)
Total Submission(s): 1806 Accepted Submission(s): 491
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
题意:略
思路:用dp[i][j][k]表示考虑到第i列,且第i列和第i-1列一共有j个地雷,第i行有k个地雷的方案数。用num[i]来表示某一行放置i个地雷有多少情况。
那么可以写出状态转移方程:
dp[i][j][k]=dp[i-1][pre_j][pre_k]*ans[k](pre_j,pre_k为前一列的状态量)
分析方程:
- 第i列有k个地雷。
- 第i-1列有j-k(pre_k)个地雷。
- 第i-2列有pre_j-pre_k个地雷。
可以得到关系式:
- pre_k=j-k.
- pre_j+k=a[i-1] (第i-1列周围的地雷数)
然后三重循环状态转移,且将最后一列所有可能的情况累加即可。(注意特殊情况的特判)
PS:此题这种做法有点卡时限,需要多提交几次。
可能的优化方法TUT。。。
把数组开小,开到刚刚好,如果dp[][][]的后两维都开到10,就一定TLE。
#include <cstdio>#include <iostream>#include <vector>#include <string>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 10005;const int mod = 1e8+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;//dp[i][j][k]表示到第i列,这一列的和前一列的地雷数为j个,并且这一列的地雷数为k个的方案数int a[maxn];char s[maxn];ll dp[maxn][5][3];int num[3]={1,2,1};int main(){ rush() { scanf("%s",s); int len=strlen(s); int flag=0; for(int i=1;i<=len;i++) { a[i]=s[i-1]-'0'; if((i==1||i==len)&&a[i]>4) flag=1; if(a[i]>6) flag=1; } if(flag) { puts("0"); continue; } if(len==1) { if(a[1]<=2) printf("%d\n",num[a[1]]); else puts("0"); continue; } mst(dp,0); for(int i=0;i<=2;i++) { if(a[1]>=i) dp[1][i][i]=num[i]; else dp[1][i][i]=0; } for(int i=2;i<=len;i++) for(int j=0;j<=4;j++) for(int k=0;k<=2&&k<=j;k++) { int pre_j=a[i-1]-k; int pre_k=j-k; if(pre_j>=0&&pre_k>=0&&pre_j>=pre_k) { dp[i][j][k]=num[k]*dp[i-1][pre_j][pre_k]; dp[i][j][k]%=mod; } } ll ans=0; for(int i=0;i<=a[len]&&i<=2;i++) { ans+=dp[len][a[len]][i]; ans%=mod; } printf("%I64d\n",ans); } return 0;}
- HDOJ 5965 扫雷 【DP】
- Hdu 5965 扫雷【思维+Dp】
- HDU --- 5965 扫雷 【dp + 思维】
- HDU 5965 扫雷(dp/状态压缩dp)
- [bzoj1088][DP]扫雷Mine
- 【状压dp】扫雷 Vijos1193 SCOI2005
- P1193扫雷 (DP状态压缩)
- bzoj1088.扫雷Mine (模拟 || DP)
- BZOJ_P1088&Codevs_P2452 [SCOI2005]扫雷(DP)
- BZOJ1088(SCOI2005)[扫雷Mine]--DP
- [BZOJ]1088: [SCOI2005]扫雷Mine[乱搞DP]
- HDU5965 扫雷 —— dp递推
- [BZOJ1088][SCOI2005]扫雷Mine(dp)
- 【状压DP】BZOJ1088(SCOI2005)[扫雷Mine]题解
- [SCOI2005] BZOJ 1088 扫雷-状压dp
- [BZOJ1088]-[SCOI2005]扫雷Mine-简单dp
- 扫雷 hdu 5965
- hdu 5965 扫雷
- JDK中对称加密DES
- Asp.net DataTable to CSV 文件
- git服务器搭建
- Hdu 2026 首字母变大写
- 数据库优化
- HDOJ 5965 扫雷 【DP】
- 【HDU 4248】组合数学 A Famous Stone Collector
- 学习笔记2017.07.08-day6,am-CSS字体
- C++using声明和using指示
- 算法导论15章 动态规划 dynamic programming 复习第二弹 最长公共子序列
- C++运算符的重载
- mvc mvp mvvm 概说
- java 经典多点面试题
- opencv在编译报错的汇总