您的位置:首页 > 其它

UVALive 5811 Cards

2017-09-13 00:13 369 查看
题意:扑克牌洗牌后一张一张发牌,对应的花色放成一堆,大小王可以放在任意堆,但是必须选择使得当前期望值最小的那一堆。当四堆花色每堆的牌数都超过了给定的值就停止发牌,问发牌数的期望值。

想到期望dp的话就可以用记忆化搜索做,停止发牌时的返回的期望是0。而且大小王的最小值的取法保证了不会走到不合法的情况。

代码:

#include<bits/stdc++.h>
using namespace std;

#define fi first
#define se second
#define pb push_back
#define CLR(A, X) memset(A, X, sizeof(A))
#define bitcount(X) __builtin_popcountll(X)
typedef long long LL;
typedef pair<int, int> PII;
const double eps = 1e-10;
const LL MOD = 1e9+7;
const auto INF = 0x3f3f3f3f;
int dcmp(double x) { if(fabs(x) < eps) return 0; return x<0?-1:1; }

double dp[15][15][15][15][5][5];
bool vis[15][15][15][15][5][5];
int b[4];

double dfs(int *a, int x, int y) {
double &t = dp[a[0]][a[1]][a[2]][a[3]][x][y];
bool &v = vis[a[0]][a[1]][a[2]][a[3]][x][y];
if(v) return t;
int cnt = 0, sum = 54;
for(int i = 0; i < 4; i++) {
int tmp = a[i]+(x==i)+(y==i);
if(tmp >= b[i]) cnt++;
sum -= tmp;
}
t = 0;
if(cnt == 4) { v = 1; return t; }
int c[4];
for(int i = 0; i < 4; i++) c[i] = a[i];
double minx = 1e18, miny = 1e18;
for(int i = 0; i < 4; i++) {
if(x == 4) minx = min(minx, dfs(c, i, y)*2/sum);
else if(y == 4) miny = min(miny, dfs(c, x, i)/sum);
if(c[i] < 13) {
c[i]++;
t += (13-c[i]+1)*dfs(c, x, y)/sum;
c[i]--;
}
}
v = 1;
if(x == 4) t += minx;
else if(y == 4) t += miny;
return ++t;
}

int main() {
int X;
scanf("%d", &X);
for(int cas = 1; cas <= X; cas++) {
int cnt = 0;
for(int i = 0; i < 4; i++) {
scanf("%d", &b[i]);
if(b[i] > 13) cnt += b[i]-13;
}
if(cnt > 2) printf("Case %d: %.3f\n", cas, -1.000);
else {
int c[4]; CLR(c, 0); CLR(vis, 0);
printf("Case %d: %.3f\n", cas, dfs(c, 4, 4));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: