期望dp+记忆化搜索
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
int C,D,H,S;
double dp[17][17][17][17][5][5];
bool vis[17][17][17][17][5][5];
double dfs(int c,int d,int h,int s,int i,int j)
{
int cc=c,dd=d,hh=h,ss=s;
if(i==1) cc--;if(j==1) cc--;
if(i==2) dd--;if(j==2) dd--;
if(i==3) hh--;if(j==3) hh--;
if(i==4) ss--;if(j==4) ss--;
if(cc>13||dd>13||hh>13||ss>13) return 0.0;
if(c>=C&&d>=D&&h>=H&&s>=S) return 0.0;
if(vis[c][d][h][s][i][j]) return dp[c][d][h][s][i][j];
vis[c][d][h][s][i][j]=true;
double ans=0.0,t;
int cnt=54-c-d-h-s;
if(!i)
{
t=min(100.0,dfs(c+1,d,h,s,1,j));
t=min(t,dfs(c,d+1,h,s,2,j));
t=min(t,dfs(c,d,h+1,s,3,j));
t=min(t,dfs(c,d,h,s+1,4,j));
ans+=t;
}
if(!j)
{
t=min(100.0,dfs(c+1,d,h,s,i,1));
t=min(t,dfs(c,d+1,h,s,i,2));
t=min(t,dfs(c,d,h+1,s,i,3));
t=min(t,dfs(c,d,h,s+1,i,4));
ans+=t;
}
ans+=(13-cc)*dfs(c+1,d,h,s,i,j);
ans+=(13-dd)*dfs(c,d+1,h,s,i,j);
ans+=(13-hh)*dfs(c,d,h+1,s,i,j);
ans+=(13-ss)*dfs(c,d,h,s+1,i,j);
ans=ans/cnt+1.0;
dp[c][d][h][s][i][j]=ans;
return ans;
}
int main()
{
int T,kase=0;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&C,&D,&H,&S);
int num=0;
num+=max(C-13,0);
num+=max(D-13,0);
num+=max(H-13,0);
num+=max(S-13,0);
printf("Case %d: ",++kase);
memset(vis,false,sizeof(vis));
if(num>2) printf("-1\n");
else printf("%.6f\n",dfs(0,0,0,0,0,0));
}
return 0;
}