ACwing217. 绿豆蛙的归宿 218. 扑克牌

2023-12-12 12:20

本文主要是介绍ACwing217. 绿豆蛙的归宿 218. 扑克牌,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

217. 绿豆蛙的归宿

题意:

给出一个有向无环的连通图,起点为 1,终点为 N,每条边都有一个长度。

数据保证从起点出发能够到达图中所有的点,图中所有的点也都能够到达终点。

绿豆蛙从起点出发,走向终点。

到达每一个顶点时,如果有 K 条离开该点的道路,绿豆蛙可以选择任意一条道路离开该点,并且走向每条路的概率为 1/K。

现在绿豆蛙想知道,从起点走到终点所经过的路径总长度的期望是多少?

分析:
求期望一般都用dp,不妨从这方面入手,设f[i]表示从i到终点的期望,则f[i] = \sum 1/k(w[i]+f[j]), 我们要求f[1], 显然终点f[N] = 0, 可以记忆化搜索一下,记忆化实际上就是dp的反向,相当于从终点往前推,即可解出该题。另外一种方式就是建反图,在反图上跑拓扑序进行dp。

记忆化代码:

# include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define x first
#define y second
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6 + 10;
const int M = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const double INFF = 0x7f7f7f7f7f7f7f7f;
const int mod = 1e9 + 7;
int n, m;
int h[N], e[N], ne[N], idx, w[N];
double f[N];
int dout[N];void add(int a, int b, int c)
{e[idx] = b, w[idx] = c ,ne[idx] = h[a], h[a] = idx ++;
}double dfs(int u)
{if(f[u] >= 0)return f[u];//期望大于等于0直接返回double res = 0;for(int i = h[u];i != -1;i = ne[i]){int j = e[i];res += (1.0 * w[i] + dfs(j))/ dout[u];}return f[u] = res;
}signed main()
{cin >> n >> m;memset(h, -1, sizeof h);while(m --){int a, b, c;cin >> a >> b >> c;add(a, b, c);dout[a] ++;//表示出边有多少}memset(f, -1, sizeof(f));//初始化一下,表示刚开始都不合法printf("%.2f", dfs(1));return 0;
}

218. 扑克牌

题意:

Admin 生日那天,Rainbow 来找 Admin 玩扑克牌。

玩着玩着 Rainbow 觉得太没意思了,于是决定给 Admin 一个考验。

Rainbow 把一副扑克牌(54 张)随机洗开,倒扣着放成一摞。

然后 Admin 从上往下依次翻开每张牌,每翻开一张黑桃、红桃、梅花或者方块,就把它放到对应花色的堆里去。

Rainbow 想问问 Admin,得到 A 张黑桃、B 张红桃、C 张梅花、D 张方块需要翻开的牌的张数的期望值 E是多少?

特殊地,如果翻开的牌是大王或者小王,Admin 将会把它作为某种花色的牌放入对应堆中,使得放入之后 E 的值尽可能小。

由于 Admin 和 Rainbow 还在玩扑克,所以这个程序就交给你来写了。

分析:
考虑dp,观察发现每个状态都有黑桃数量红桃数量梅花方块数量,和大小王的状态,不妨以此定义状态f[a][b][c][d][x][y], 表示目前卡片数量和大小王状态(0 1 2 3 4)4表示还没翻到. 

代码:
 

# include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define x first
#define y second
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 20;
const int M = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const double INFF = 1e20;
const int mod = 1e9 + 7;
int A, B, C, D;
double f[N][N][N][N][5][5];double dfs(int a, int b, int c, int d, int x, int y)
{double & v =  f[a][b][c][d][x][y];if(v >= 0)return v;double res = 1;int as = a + (x == 0) + (y == 0), bs = b +(x == 1) + (y == 1);int cs = c + (x == 2) + (y == 2), ds = d + (x == 3) + (y == 3);int sum = a + b + c + d + (x != 4) + (y != 4);if(as >=A&&bs>=B&&cs>=C&&ds>=D)return v = 0;if(sum >= 54){return v = INFF;}if(a < 13){res += (13.0 - a)/(54-sum)*dfs(a + 1, b, c, d, x, y);}if(b < 13){res += (13.0 - b)/(54-sum)*dfs(a, b+1, c, d, x, y);}if(c < 13){res += (13.0 - c)/(54-sum)*dfs(a, b, c+1, d, x, y);}if(d < 13){res += (13.0 - d)/(54-sum)*dfs(a, b, c, d+1, x, y);}if(x == 4){res += min({1.0/(54-sum)*dfs(a, b, c, d, 0, y), 1.0/(54-sum)*dfs(a,b,c,d,1,y),1.0/(54-sum)*dfs(a,b,c,d,2,y),1.0/(54-sum)*dfs(a,b,c,d,3,y)});}if(y == 4){res += min({1.0/(54-sum)*dfs(a, b, c, d, x, 0), 1.0/(54-sum)*dfs(a,b,c,d,x,1),1.0/(54-sum)*dfs(a,b,c,d,x,2),1.0/(54-sum)*dfs(a,b,c,d,x,3)});}return v = res;
}signed main()
{cin >> A >> B >> C >> D;    memset(f, -1,sizeof(f));double ans = dfs(0, 0, 0, 0, 4, 4);if(ans > INFF/2)ans = -1;printf("%.3f", ans);return 0;
}

这篇关于ACwing217. 绿豆蛙的归宿 218. 扑克牌的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/484630

相关文章

【剑指offer】扑克牌顺子(字符串)

题目描述 LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5

C#控制台实现52张扑克牌的分法

52张牌随机分给4个万玩家,要求每个玩家的牌用一个一维数组表示。 我们采用模拟大法。初始化一副扑克牌,洗牌,发牌。 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace ConsoleApplication

CodeForces Round 218 D. Vessels(学姐我没用线段树系列)

这道题的意思是给你一个水塔,可以从中间任意一层倒水,告诉你每一层的容量,这一曾层满后水会流入下一层,总共有N层,再满了就直接流到地上。然后给出N个操作 操作1:往第n层中加x的水 操作2:询问每一层装有多少水 用BIT保存所剩空间的前缀和,每次加水的时候二分最终水会流到哪一层,然后加水的时候依次更新BIT,虽然式单点更新但是每一次更新都会直接把该层的空间沾满,下一次不会再更新,所以总共是O(

剑指offer(C++)--扑克牌顺子

题目 LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为1

JAVA编程思想:斗地主扑克牌

斗地主大家都玩过,扑克牌一共54张牌,底牌三张剩下的51张正好是每人17张。 我们需要干的事情就是: 1. 先获取54张牌, 2. 把它打乱, 3. 抽出去三张底牌, 4. 将51张平均分给三个人 我们之前学到过多种集合,list,set,map,实现这个我们应该选择哪种数据结构呢? 答案是:MAP 为什么是MAP我们来分析一下,我们都知道斗地主发牌之后,我们到手里面的牌最好是有序的,方

愿得一人心——祭奠······埋葬我218的爱情

曾在我背包小小夹层里的那个人 陪伴我漂洋过海经过每一段旅程 隐形的稻草人 守护我的天真 曾以为爱情能让未来只为一个人 关了灯依旧在书桌角落的那个人 变成我许多年来纪念爱情的标本 消失的那个人 回不去的青春 忘不了爱过的人才会对过往认真 只愿得一人心 白首不分离 这简单的话语 需要巨大的勇气 没想过失去你 却是在骗自己 最后你深深藏在我的歌声里 只愿得一人心 白首

Java 扑克牌发牌

Java 扑克牌发牌 今天看到这个算法题,http://www.cnblogs.com/xishuai/p/3392981.html ,忍不住自己用Java做了一个。 初始化很重要,所有的52张牌按顺序放入到容器里边,标志位标记为false表示手里没这牌。 1 发牌 利用随机数,找到容器中的这张牌,将标志位标记为true,表示手里有了这张牌。 2 排序 因为放入的时候是按顺序的,于是每个

[剑指Offer]-扑克牌中的顺子

题目描述 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。其中A为1,J为11,Q为12,K为13,而大小王为0,且大小王能够当做任意一张牌。 解题思路 首先应该对数组进行排序。统计数组中大小王(0)出现的个数。统计数组中所有相邻数之间的间隔。同时还需要排除对子的情况,如果出现了对子,那么肯定不可能是顺子(0除外)。最后比较0的个数和间隔大小,如果0的个数大于等于间隔数,

NYOJ 218题 Dinner

题目中竟然有提示,我没看到,苦苦想了这么多表示餐具的英文单词,而且还wa了。 不过,发现一个好玩的事情。输入的时候按照样例输入3 basketball fork chopsticks,然后程序输出fork chopsticks;如果把空格换成回车,那么,在输入fork时,立即输出fork,在输入chopsticks时,立即输出一个chopsticks。

扑克牌游戏

完整代码: #include <iostream>#include <string>#include <conio.h>#include <stdlib.h>#include <stdio.h>#include <time.h> #include <algorithm>using namespace std;class Playing_Card //扑克类{//private