

题目大意:有三种天气和四种湿度,给出在每种天气下四种湿度的概率,和天气之间的转移概率,现在给出一个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;
}
hdu 4865 Peter's Hobby(2014 多校联合第一场 E),布布扣,bubuko.com
hdu 4865 Peter's Hobby(2014 多校联合第一场 E)
原文地址:http://blog.csdn.net/dyx404514/article/details/38239085