【LightOJ 1274】Beating the Dataset(概率DP)

【LightOJ 1274】Beating the Dataset(概率DP)

题目大意:
一道题目有多个输出文件。
每个文件有一个输出,”YES”或”NO”
现在直接提交答案,从”YES”开始,如果与后台答案不同时,下一次输出”NO”,以此类推,如果相同则接着输出上一次的答案。

给出n,表示后台n个输出,s表示输出文件的总大小,一个”YES”占3Byte
一个”NO”占2Byte

问判完最后一个输出后,错误的组数的期望。

初步思路:
dp[i][0] 表示当前是第i字节,并且下一步要输出YES
dp[i][1] 表示当前是第i字节,并且下一步要输出NO
后来发现输出爆炸,原因是这样来做,固定的s最终的结果会对应多种n,但固定n和s后,YES和NO的数量就固定了。

对啊!YES和NO固定的。思路2:
dp[i][j][0] 表示i个YES j个NO,下一步输出YES
dp[i][j][1] 表示i个YES j个NO,下一步输出NO
开不下。然后想到用时间换空间,但是这样时间也已经很爆炸了!

可能最近比较频繁做类似的题,想到边遍历边转移。也就是把一维状态在for循环中表现出来。
从1到n遍历,表示当前剩下i个文件没评测。
第二层循环YES的个数,表示剩下j个文件是YES
这不就是滚动数组吗!

然后转移搞一下就出来了
代码如下:

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;
const int msz = 5555;

double dp[msz][2];

int main()
{
    int t,n,s;

    scanf("%d",&t);

    for(int z = 1; z <= t; ++z)
    {
        scanf("%d%d",&n,&s);

        //Num of "YES"
        int a = s-2*n;

        memset(dp,0,sizeof(dp));

        for(int i = 1; i <= n; ++i)
        {
            int p = i;

            //printf("%d:\n",i);

            for(int j = a; j >= 0; --j)
            {
                //i is "NO"
                if(j < i)
                {
                    dp[j][0] = (dp[j][1]+1)*(i-j)/p;
                    dp[j][1] = dp[j][1]*(i-j)/p;
                }
                else dp[j][1] = dp[j][0] = 0;

                //i is "YES"
                if(j >= 1 && j <= i)
                {
                    dp[j][0] += dp[j-1][0]*j/p;
                    dp[j][1] += (dp[j-1][0]+1)*j/p;
                }

                //printf("prt:YES useYES:%d %f\n",j,dp[j][0]);
                //printf("prt:NO useYES:%d %f\n",j,dp[j][1]);
            }
        }

        printf("Case %d: %.11f\n",z,dp[a][0]);
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值