1637 - Double Patience(状态转移+求成功概率)

用九元组表示当前状态,即每队牌剩的张数,状态总数为5^9=1953125.

设d[ i ]表示状态i对应的成功概率,则根据全概率公式,d[ i ]为后继成功概率的平均值,按照动态规划的写法计算即可。

这个动态规划我不会写,帅哥思路真的很清晰很好啊。

但是学会还是很高兴的

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))

vector<char> v[9];
double d[5][5][5][5][5][5][5][5][5];
int vis[5][5][5][5][5][5][5][5][5];
double dp(int t0,int t1,int t2,int t3,int t4,int t5,int t6,int t7,int t8)
{
    double& ans=d[t0][t1][t2][t3][t4][t5][t6][t7][t8];
    if(vis[t0][t1][t2][t3][t4][t5][t6][t7][t8]) return ans;
       vis[t0][t1][t2][t3][t4][t5][t6][t7][t8]=1;
    int te[9]={t0,t1,t2,t3,t4,t5,t6,t7,t8};
    int ok=1;
    for(int i=0;i<9;i++) if(te[i]){ok=0; break;}
    if(ok) return ans=1;
    ans=0;
    int num=0;
    double pum=0;
    for(int i=0;i<9;i++) if(te[i])
        for(int j=i+1;j<9;j++) if(te[j]&&v[i][te[i]-1]==v[j][te[j]-1])
        {
            num++;
            te[i]--; te[j]--;
            pum+=dp(te[0],te[1],te[2],te[3],te[4],te[5],te[6],te[7],te[8]);
            te[i]++; te[j]++;
        }
    if(num==0) return ans=0;
    else return ans = pum/(num*1.0);
}

int main()
{
    char s[5];
    while(scanf("%s",s)!=EOF)
    {
        mem(d);
        mem(vis);
        for(int i=0;i<9;i++)
            v[i].clear();
        v[0].push_back(s[0]);
        for(int i=1;i<=3;i++)
        {
            scanf("%s",s);
            v[0].push_back(s[0]);
        }
        for(int i=1;i<9;i++)
        {
            for(int j=1;j<=4;j++)
            {
                scanf("%s",s);
                v[i].push_back(s[0]);
            }
        }
        printf("%lf\n",dp(4,4,4,4,4,4,4,4,4));
    }
    return 0;
}

定义状态的方法和状态转移的方法都很好,要学习。

方法值得常思考常学习~

1637 - Double Patience(状态转移+求成功概率)

时间: 2024-10-14 03:46:58

1637 - Double Patience(状态转移+求成功概率)的相关文章

1637 - Double Patience (概率DP)

一道状态较多的概率DP,想要表示所有的状态显然要拓展几个维度表示九堆牌当前的状态 . 但是这么写太复杂,所以我们不妨用一个vector来储存状态,将dp数组用一个map来表示,即 map<vector<int> ,double> d; 利用vector可以作为函数参数传递这个优点,将大大节省代码量 . 概率很好求,在每一次迭代中,寻找所有可以转移的状态数tot,那么状态转移就是d[i] = sum(d[i-1])/tot . 也就是全概率公式 . 递归边界是当所有牌都被摸走了,返回

uva 1637 Double Patience

https://vjudge.net/problem/UVA-1637 36张牌分成9堆,每堆4张牌.每次可以拿走某两堆顶部的牌,但需要点数相同. 如果有多种拿法则等概率的随机拿. 如果最后拿完所有牌则游戏成功.按顺序给出每堆牌的4张牌,求成功概率. #include<cstdio> using namespace std; char s[10][5]; char ss[5]; int left[10]; int v[2000001]; double dp[2000001]; int t; i

UVA 1637 Double Patience 概率DP

Double Patience Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Double Patience is a single player game played with a standard 36-card deck. The cards are shuffled and laid down on a table in 9 pile

(review)zoj4800 二维dp 状态转移很灵活

1 #include<iostream> 2 #include<stdio.h> 3 4 using namespace std; 5 6 double dp[10005][125]; 7 double p[125][125]; 8 int pk[10005]; 9 10 int N,M; 11 12 double fmax(double a,double b){ 13 if(a-b>0) return a;else return b; 14 } 15 int main(){

[Uva1637][DFS][记忆化] 纸牌游戏 Double Patience

写代码一定要注意!!!!!! 我因为i+1写成了1+1改了一晚上!!!!!!(菜都写脸上了) 题目: Double Patience是一种单人游戏,使用标准的36张牌组.这些牌在洗牌后放在一张桌子上,叠成9叠,每叠4张,面朝上. 牌放下后,玩家转身.每一次,他可以从任意两个牌堆中取出同一等级的顶级牌,然后将它们移除.如果有几种可能性,玩家可以选择任何一种.如果所有的牌都从桌上移除,玩家将赢得游戏,如果一些牌仍然在桌上,并且没有有效的移动,玩家将失败. 乔治喜欢这种游戏.但当有几种可能时,他不知道

《概率统计》状态转移:初识马尔科夫链

回顾两类重要的随机过程 在上一篇随机过程的概述中,我们提到过两类非常非常典型且重要的随机过程,一类是:伯努利过程和泊松过程,这一类随机过程是无记忆性的,也就是说未来的状态不依赖于过去的状态--新的"成功"或"到达"不依赖于该过程过去的历史情况. 而另一类则正好相反,未来的情况会依赖于过去的情况,并且能够在某种程度上通过过去发生的情况去预测未来,例如这一篇我们的核心内容--马尔科夫过程,它在许许多多的领域都有深入和广泛的应用. 离散时间的马尔科夫链 马尔科夫链三要素

读懂TCP状态转移

读懂TCP状态变换的过程,对于理解网络编程颇有帮助,本文将对TCP状态转移过程进行介绍,但各个状态(总共11个)的含义不在本文介绍的范围. 内容来源:<UNIX网络编程>第一卷第二章2.6节,若是读者对某个知识点不太理解,请参考原文. TCP状态转换图(state transition diagram) 1. 建立连接(three-way hand shake) 主动打开(passive open):服务器必须准备好接受外来的连接,通常通过socket.bind和listen完成. 被动打开(

iptables ip报文 tcp报文 tcp三次握手四次端口 有限状态机 状态转移

linux 网络防火墙 netfilter :是内核的一个frame :框架 iptables :数据报文过滤:nat mangle等规则生成工具 网络知识: IP报文首部   tcp报文首部 hdr len   报头首部长度  给出的字节需要乘以横向 32/8 = 4字节 Type of Service(服务类型)    服务类型 Total Length(总长度)          报文总长度    包括表头与内容 (Data) 部分.最大可达 65535 bytes.   注: 报文总长度

uva 10795 - A Different Task (递归+状态转移)

题目链接:uva 10795 - A Different Task 思路来源于:点击打开链接 题意: 新汉若塔问题,有n个盘子,放在3个盘子上,给你一个初始状态和一个结束状态,问你最小步数怎样到达. 思路: 递归+状态转移,直接从初态到末态好像不是那么好办,对最大的一块n,首先肯定要把他放在末态的位置上,假设开始在1号位置,要放到3号位置,那么必须先到达这个状态s:1~n-1必须都从大到小放在2上面,然后放n,然后将1~n-1转移到末态,由对称性,也即可以变为末态转移到状态s,那么处理起来就可以