upc 个人训练赛第十五场:炸弹安放(dp)

问题 D: 炸弹安放

题目描述
小蔡决定在小头家门口安放炸弹!!
小头家门口有n个连续的格子排成一行,对于每个格子,小蔡可以决定放一颗炸弹或者不放。为了防止小头被炸死,小蔡不会在连续3个格子都放上炸弹。小蔡想知道一共有多少安放炸弹的方案(可以一个也不放)。
由于方案数可能很多,所以你只需要方案个数mod 55555就可以了。
输入
一个正整数,即n(n≤1000)
输出
仅包含一个整数,即答案
样例输入 Copy
4
样例输出 Copy
13
提示
对于样例1的解释,一共有4个格子,每个格子可以选择放或者不放,因此根据乘法原理共有222*2=16种方案,其中在(1,2,3)上放炸弹是不合法的,会炸死小头。同样(2,3,4)和(1,2,3,4)也都不合法,所以一共有16-3=13种方案
13 mod 55555=13,因此答案为13

思路:
这个题我用了一个非常简单粗暴地办法,我计算了前几项的值然后找到了这些数字之间的规律:
1 2 4 7 13 24 44 81 …
我们可以发现,从第四项开始,每一项都是前三项之和

//我的方法
const int mod = 55555;
int n;
int a[1005];
int main()
{
    cin >> n;
    a[0] = 1,a[1] = 2,a[2] = 4;
    for(int i=3;i<=n;i++)
    {
        a[i] = (a[i-1]+a[i-2]+a[i-3]) % mod;
    }
    printf("%lld\n",a[n]);
    return 0;
}

But这道题正解是dp,经过学长dalao的细心讲解,我终于搞明白了这道题!
dp[i][j] 表示第i个格子连续放了j个炸弹,它一共只有三种状态,连续放了0个炸弹,1个炸弹,2个炸弹
dp[1][0] = dp[1][1] = 1表示第1个格子连续放了0个炸弹的方案有1种,连续放了1个炸弹的方案有1种
dp[2][0] = 2表示第2个格子连续放了0个炸弹的方案数有两种,可以是第一个格子放炸弹第二个不放或者第二个格子放炸弹第一个不放,这两种情况都是连续0个炸弹
dp[2][1] = dp[2][2] = 1表示第2个格子连续放了1个炸弹的方案数是1种,即第二个格子放了炸弹;第2个格子连续放了2个炸弹的方案数是1种,即第一个第二个格子都放了炸弹
推到这里基本方程就出来了
dp[i][0] = dp[i-1][0] + dp[i-1][1] + dp[i-1][2]
dp[i][1] = dp[i-1][0]
dp[i][2] = dp[i-1][1]

const ll mod = 55555;
ll dp[maxn][3];
int main()
{
	int n; cin >> n;
	
	dp[1][0] = dp[1][1] = 1;
	dp[2][0] = 2;
	dp[2][1] = dp[2][2] = 1;
	
	for(int i=3;i<=n;i++)
	{
		dp[i][0] = dp[i-1][0] + dp[i-1][1] + dp[i-1][2];dp[i][0] %= mod;
		dp[i][1] = dp[i-1][0]; 
		dp[i][2] = dp[i-1][1];
	}
	printf("%lld\n",(dp[n][0] + dp[n][1] + dp[n][2])%mod);
	return 0;
}
发布了60 篇原创文章 · 获赞 1 · 访问量 2143

猜你喜欢

转载自blog.csdn.net/magic_wenge/article/details/105549685
UPC