hdu 4865 Peter's Hobby 2014 Multi-University Training Contest 1

这一题我开始还用贝叶斯公式推了半天木有推出来,后来看到正解是Markov model == 当初上机率的时候老师最后都没讲这个chapter。然后我看百度百科举得例子居然和题目是一种。

Markov模型讨论的是状态之间的转移概率,转移的时候只和当前状态有关,转移的概率矩阵不随时间变化,所以可以根据初始状态算出之后的某个状态的概率,题目里面的case是隐式Markov Model引入了两个随机过程。

Markov Model的性质是:Xn+1对于过去条件的几率分布只与Xn有关,所以题目里的概率就是直接相乘(我开始还在条件概率里面绕了好久==)

dp[i][x]=max(dp[i][x],dp[i-1][y]*q[y][x]*p[x][c]),dp[i][x]表示第i天的天气是x,y表示i-1天的天气。

然后再用pre[i][x]记录前驱,即上式中max的y,再递归打印路径即可。

注意这里面虽然给了第一天各种天气的概率,但是因为input还定了第一天的humidity,所以dp[1][x]=p*p[1][humidity[1]];相当于 P(A&&B)。之前把这个漏了,我还纳闷给第一天的湿度有啥用。><

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include <ctype.h>
#include<map>
using namespace std;
//hdu 4865
const int maxn=50;
int T;
int n;
int humidity[maxn];
map<string,int>mp;
double p[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 q[3][3]={0.5,0.375,0.125,0.25,0.125,0.625,0.25,0.375,0.375};
double dp[maxn][3];
int pre[maxn][3];
void initial()
{
    mp["Dry"]=0;
    mp["Dryish"]=1;
    mp["Damp"]=2;
    mp["Soggy"]=3;
}
void DP()
{
    memset(dp,0,sizeof(dp));
    memset(pre,0,sizeof(pre));
    dp[1][0]=0.63*p[0][humidity[1]];//day 1 除了满足给定的天气还要满足humidity,相当于P(AB)
    dp[1][1]=0.17*p[1][humidity[1]];
    dp[1][2]=0.2*p[2][humidity[1]];
   // cout<<dp[1][0]<<" " <<dp[1][1]<<" "<<dp[1][2]<<endl;
    for(int i=2;i<=n;i++)
    {
        int c=humidity[i];
        for(int x=0;x<3;x++)
        {
            for(int y=0;y<3;y++)
            {
                double tmp=dp[i-1][y]*q[y][x]*p[x][c];
                if(tmp>dp[i][x])
                {
                    dp[i][x]=tmp;
                    pre[i][x]=y;
                }
            }
        }
    }

}
void print(int n,int x)
{
    string str[]={"Sunny","Cloudy","Rainy"};
    if(n==1)
    {
        cout<<str[x]<<endl;
        return;
    }
    print(n-1,pre[n][x]);
    cout<<str[x]<<endl;
}
int main()
{
    freopen("input.txt","r",stdin);
   //  freopen("data.txt","r",stdin);
    // freopen("out1.txt","w",stdout);
    initial();
    scanf("%d",&T);
    for(int t=1;t<=T;t++)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            string s;
            cin>>s;
            map<string,int>::iterator it;
            it=mp.find(s);
            int c=it->second;
            humidity[i]=c;
        }
        //for(int i=1;i<=n;i++)  cout<<humidity[i]<<endl;
        DP();
        int mx=0;
        double tmp=dp[n][0];//之前把dp 和 tmp敲成了int,结果舍尾变成0了。。
        for(int i=1;i<3;i++)
        {
            //cout<<dp[n][i]<<" "<<tmp<<endl;;
            if(tmp<dp[n][i])
            {
              //  cout<<"here"<<endl;
                tmp=dp[n][i];
                mx=i;
            }
        }
    //   cout<<mx<<endl;
        printf("Case #%d:\n",t);
        print(n,mx);

    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值