fzoj 1342 Tight Words(DP:递推)

看起来很凶残的一道题,但其实还是比较好做的

找到对应的状态转移方程就好做了

我是用打表法一次把结果全打出来了

时间复杂度是O(10×10×100)

0ms代码及注释如下:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;

double sum[110][11];
double dp[110][11][11];
    /*dp[k][i][n]
     *k表示给定的集合中有k+1个元素
     *i表示当前字符排列以i结尾
     *n表示字符串长度
     *dp[n][k][i] = dp[n-1][k][i-1]+dp[n-1][k][i]+dp[n-1][k][i+1]
     *0 <= i <= k
     */
int main(void) {
    
    int n, k, i;

    memset(sum, 0, sizeof(sum));

    for(k=0; k<10; ++k) {
        for(i=0; i<=k; ++i)
            dp[1][k][i] = 100.0;
    }

    for(n=1; n<101; ++n) {
        for(k=0; k<10; ++k) {
            for(i=0; i<=k; ++i) {
                if(i-1 >= 0)
                    dp[n][k][i] += dp[n-1][k][i-1];
                if(i+1 <= k)
                    dp[n][k][i] += dp[n-1][k][i+1];
                dp[n][k][i] += dp[n-1][k][i];
                sum[n][k] += dp[n][k][i];
            }
            for(int j=0; j<n; ++j)
                sum[n][k] /= k+1.0;
        }
    }

    while(scanf("%d%d", &k, &n) != EOF) {
        printf("%.5lf\n", sum[n][k]);
    }

    return 0;
}


如果不用打表我的代码对应的就是2重循环

但是在ppt上看了用滚动数组优化的做法

OTZ

代码如下:

#include <cstdio>
using namespace std;

int main(){
    int k, n, i, t;
    double f[12], tmp[12], ans;
    while(scanf("%d%d", &k, &n) != EOF) { 

		//f[i]表示以i为最后一位的满足条件字符串的总数

        for(i=0; i<=k; ++i) 
            f[i] = 100.0/(k+1.0);

        for(t=2; t<=n; ++t) {//共循环n次

            tmp[0] = (f[0]+f[1]) / (k+1.0);

            for(i=1; i<=k-1; ++i) 
                tmp[i] = (f[i-1]+f[i]+f[i+1]) / (k+1.0);

            tmp[k] = (f[k-1]+f[k]) / (k+1.0);

			//滚动数组优化,上一状态用不到了
            for(i=0; i<=k; ++i)
                f[i] = tmp[i];
        }

        for(ans=0.0,i=0; i<=k; ++i) 
            ans+=f[i];
        printf("%.5lf\n", ans);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值