题解 [JLOI2013] 卡牌游戏

主要思路:

玩家id为[0,n-1],枚举到i玩家,将其临时id当成0,则初始庄家的临时id为(n-i),dp[i][j]表示i玩家坐庄,还剩j个人时的胜率

用记忆化搜索来实现

注意:

1.i号玩家出局时,下一次庄家的id即为i%(tot-1)(tot是当前玩家数)

分两种情况:i=tot-1时,下一次的庄家即为0,(tot-1)%(tot-1)==0;

i<tot-1时,下一次的庄家即为i,i%(tot-1)==i;

2.当转到0玩家,也就是当前求其胜率的人,continue

代码如下

#include <bits/stdc++.h>
using namespace std;
#define LL long long
int n,m,Num[510];
double dp[510][510];
int mark[510][510];
double dfs(int k,int p) {
	k=k%p;//当k==p时,应从0玩家开始
	if(mark[k][p])return dp[k][p];
	int x;
	double res=0;
	for(int i=1; i<=m; ++i) {
		x=(k+Num[i]-1)%p;
		if(x!=0)res+=dfs(x,p-1)/(1.0*m);//x==0则舍去
	}
	mark[k][p]=1;
	return dp[k][p]=res;
}
int main() {
	cin>>n>>m;
	for(int i=1; i<=m; ++i) {
		scanf("%d",&Num[i]);
	}
	for(int i=0; i<n; ++i) {
		memset(mark,0,sizeof mark);
		memset(dp,0,sizeof dp);
		mark[0][1]=1;//设置终止条件
		dp[0][1]=1;
		printf("%.2lf%%",100*dfs(n-i,n));//要求用百分数输出
		if(i!=n-1)printf(" ");			//printf输出‘%’需打两个%
	}

	return 0;
}
posted @ 2021-06-02 19:37  We269  阅读(60)  评论(0)    收藏  举报