UVa 580-Critical Mass

题目大意:n个盒子摆放成一排,当有3个以上U摆放在一起的时候,就会有危险,让你求出总共有多少中危险的情况。

小结:

DP,每放置一个新的盒子,都对应2种情况:

f(n)=当盒子数目为n的情况下,符合要求的放置方法的个数。

(1)前面n-1个盒子已经能符合要求,则第n个盒子无论是U还是L,都满足情况。

(2)前面n-1个盒子不能符合要求,即只有最后4个满足情况LUUU并且前面并没有连续的三个U的情况才能满足情况。

然后就有

状态转移方程:dp[n]=2*dp[n-1]+(1<<(n-4))-dp[n-4]

当然,还有另外一种想法,递推。

关于递推的思想,我作为新手的唯一感想就是这个想法的大致套路就是分类讨论了,在确保所有情况都已经掌握的情况下,再进行递推。

同样地,设dp[n]=n个盒子排列时满足条件的情况个数

则可得出递推方程:


然后就是关键的代码了,因为UVa我没有账号,所以无法确保我的代码一定能AC,但是测试当n=4,5,30的时候结果都是正确的,我想应该没什么问题吧.

DP做法:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<ctype.h>
using namespace std;
typedef long long ll;

int main()
{
    int n;
    ll dp[50];
    memset(dp,0,sizeof(dp));
    dp[3]=1;
    dp[4]=3;
    for(int i=5;i<=30;i++)
    dp[i]=2*dp[i-1]+(1<<(i-4))-dp[i-4];
    while(~scanf("%d",&n))
    {
        printf("%lld\n",dp[n]);
    }
    return 0;
}
递推做法:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
ll solve(ll *dp,int cur)
{
    ll ans=0;
    for(int i=1;i<=cur-3;i++)
    ans+=((1<<(i-1))-dp[i-1])*(1<<(cur-i-3));
    return (1<<(cur-3))+ans;
}
int main()
{
    int n;
    ll dp[35];
    memset(dp,0,sizeof(dp));
    dp[3]=1;
    dp[4]=3;
    for(int i=5;i<=30;i++)
    {
        dp[i]=solve(dp,i);
    }
    while(~scanf("%d",&n))
    {
        printf("%lld\n",dp[n]);
    }
    return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值