hdu 4865 Peter's Hobby(2014 多校联合第一场 E)

Peter's Hobby

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 545    Accepted Submission(s): 237


Problem Description
Recently, Peter likes to measure the humidity of leaves. He recorded a leaf humidity every day. There are four types of leaves wetness: Dry , Dryish , Damp and Soggy. As we know, the humidity of leaves is affected by the weather. And there are only three kinds of weather: Sunny, Cloudy and Rainy.For example, under Sunny conditions, the possibility of leaves are dry is 0.6.
Give you the possibility list of weather to the humidity of leaves.


The weather today is affected by the weather yesterday. For example, if yesterday is Sunny, the possibility of today cloudy is 0.375.
The relationship between weather today and weather yesterday is following by table:


Now,Peter has some recodes of the humidity of leaves in N days.And we know the weather conditons on the first day : the probability of sunny is 0.63,the probability of cloudy is 0.17,the probability of rainny is 0.2.Could you know the weathers of these days most probably like in order?

题目大意:有三种天气和四种湿度,给出在每种天气下四种湿度的概率,和天气之间的转移概率,现在给出一个n天的湿度序列,要求给出一个概率最大的天气序列。

思路:很简单的概率DP,转移概率和状态概率都给好了,设dp[i][j]表示第i天是第j种天气的最大概率,然后pre[i][j]来记录序列顺序。

假设第i-1天是第j1种天气,第i天是j2种天气,天气转移概率为p1[j1][j2],第i天的湿度为x,在第j2种天气下x湿度的概率为p2[j2][x],则有:

dp[i][j2]=max(dp[i-1][j1]*p1[j1][j2]*p2[j2][x]),记录最大值是由哪一个j1转移过来的,用pre[i][j2]记录。最后求得最大的dp[n][j],根据pre数组输出路径即可。

注:题目中说由于dp[n][j]可能很小,用double乘可能会掉精度,所以要用log,但是我直接乘也过了,可能是运气比较好吧,以后这种问题还是要多注意。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string>
#include <map>
#include <vector>
#define maxn 55
using namespace std;
double dp[55][3];
int pre[55][3];
map<string,int> mp;
string str;
double p1[3][4]={0.6,0.2,0.15,0.05,0.25,0.3,0.2,0.25,0.05,0.1,0.35,0.5};
double p2[3][3]={0.5,0.375,0.125,0.25,0.125,0.625,0.25,0.375,0.375};
void init()
{
    mp.insert(make_pair("Dry",0));
    mp.insert(make_pair("Dryish",1));
    mp.insert(make_pair("Damp",2));
    mp.insert(make_pair("Soggy",3));
}
int main()
{
    int ncase,T=0;
    scanf("%d",&ncase);
    init();
    while(ncase--)
    {
        printf("Case #%d:\n",++T);
        int n;
        scanf("%d",&n);
        cin>>str;
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<3;j++)
            dp[i][j]=0;
        }
        int lab=mp[str];
        memset(pre,0,sizeof(pre));
        dp[1][0]=0.63*p1[0][lab];
        dp[1][1]=0.17*p1[1][lab];
        dp[1][2]=0.2*p1[2][lab];
        for(int i=2;i<=n;i++)
        {
            cin>>str;
            int lab=mp[str];
            for(int j=0;j<3;j++)
            {
                for(int k=0;k<3;k++)
                {
                    double pp=dp[i-1][k]*p2[k][j]*p1[j][lab];
                    if(pp>dp[i][j])
                    {
                        dp[i][j]=pp;
                        pre[i][j]=k;
                    }
                }
            }
        }
        vector<int> ans;
        double mi=0;
        int po;
        for(int i=0;i<3;i++)
        {
            if(dp[n][i]>mi)
            {
                mi=dp[n][i];
                po=i;
            }
        }
        ans.push_back(po);
        int now=n;
        while(now!=1)
        {
            po=pre[now][po];
            ans.push_back(po);
            now--;
        }
        for(int i=n-1;i>=0;i--)
        {
            if(ans[i]==0)
            printf("Sunny\n");
            else if(ans[i]==1)
            printf("Cloudy\n");
            else
            printf("Rainy\n");
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值