HDU 5965(三行扫雷 dp)

Posted taskr212

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5965(三行扫雷 dp)相关的知识,希望对你有一定的参考价值。

 

题意是在一个 3 行 n 列的图上进行扫雷,中间一行没有雷,且中间一行的每一格都会显示周围的雷数,问根据已知的雷数在上下两行设置地雷的方法数。

分析知每一列所填雷数的和与周围的雷数有关,但每列具体的填法只影响方法数,不影响周围的雷数统计,而且每列的雷数只有 0,1,2 这三种,

用数组 dp[ ] 来记录每列的雷数,用数组 a[ ] 来记录所给的信息( 每一列出现的周围雷数的统计 ),则:

dp[ pos ] = a[ pos - 1 ] - dp[ pos - 1 ] - dp[ pos - 2 ];

dp[ 0 ] = 0 

令 dp[ 1 ] = 0,用转移方程得到数组 dp[ ] 之后,对于每一列雷数和为 0 或 2 的情况,该列都只有一种填法,而对于每一列雷数和为 1 的情况,该列有两种填法,

用乘法原理可知:当 dp[ 1 ] = 0 时,ans =  pow(2, 单列雷数和为 1 的列数);

同理,再求出当 dp[ 1 ] = 1 和 dp[ 1 ] = 2 的 ans,答案即为三个 ans 的和,但要注意若在求解 dp[ ] 的过程中出现所填雷数已超过规定雷数的情况或者要填多于 2 的

雷数,则该情况下的 ans不能被求和 (事实上也无法正确求出 ans )

分析样例:22

技术分享图片

i 的值分别取 0,1,2,则 dp[ 1 ] = {0,1,2},dp[ 2 ] 则分别填 2,1,0,

那么答案就是 sum = 1( dp[ 1 ] = 0, dp[ 2 ] = 2 ) + 4 ( dp[ 1 ] = 1, dp[ 2 ] = 1 ) + 1( dp[ 1 ] = 2, dp[ 2 ] = 0 ) = 6 

代码如下:

技术分享图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int mod = 1e8+7;
 4 int main()
 5 {
 6     std::ios::sync_with_stdio(false);
 7     int t,len,pos,f,a[10005],dp[10005];
 8     long long ans,sum;
 9     string s;
10     cin >>t;
11     while(t--)
12     {
13         cin >> s;
14         len = s.length();
15         for(int i = 0; i < len; ++i)
16             a[i+1] = s[i] - 0;
17         sum = 0;
18         for(int i = 0; i <= a[1] && i <= 2; ++i)
19         {
20             ans = 1;
21             f = 1;
22             dp[0] = 0;
23             dp[1] = i;
24             for(pos = 2; pos <= len; ++pos)
25             {
26                 dp[pos] = a[pos-1] - dp[pos-1] - dp[pos-2];
27                 if(dp[pos]<0||dp[pos]>2)
28                 {
29                     f = 0;
30                     break;
31                 }
32             }
33             if(pos==len+1 && dp[len]+dp[len-1]!=a[len])
34                 f = 0;
35             if(f)
36             {
37                 for(int j = 1; j <= len; ++j)
38                     if(dp[j]==1) ans=ans*2%mod;
39                 sum = (ans+sum)%mod;
40             }
41         }
42         cout << sum << endl;
43     }
44     return 0;
45 }
View Code

 

感谢这些博客的作者:

与本题题解相关:

https://blog.csdn.net/elbadaernu/article/details/54773033

https://www.cnblogs.com/heimao5027/p/6033812.html

关于手动扩大栈内存(第二篇题解中涉及到这种用法,但本人的题解思路主要借鉴了第一篇题解):

https://blog.csdn.net/shahdza/article/details/6586430

https://blog.csdn.net/f_zyj/article/details/51467501

https://www.cnblogs.com/aininot260/p/9627100.html

关于GCC优化:

https://blog.csdn.net/u010796610/article/details/69352484

https://blog.csdn.net/jiayanhui2877/article/details/11615471

以上是关于HDU 5965(三行扫雷 dp)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5965 扫雷

HDU-5965 扫雷

HDU 5965 扫雷

HDU 5965 扫雷 模拟 (中国大学生程序设计竞赛(合肥))

HDU 5965 枚举模拟 + dp(?)

HDU 1176 逆向dp very easy~