原题: https://cn.vjudge.net/problem/Gym-101933E
题意:
我方n人,血量已知,对方m人,血量已知。现在有d点伤害,一点一点扣,每次伤害对所有活着的人的概率相同。问d次伤害后对面全死的概率
解析:
血量最多只有6,人数最多5,可以暴力dfs。用两个数组分别表示双方血量为i的人有多少个,那么每次dfs,就可以算出转移到下一状态的概率。
叠到一个long long的话,如果前6位代表对方,那么直接state<1000000就可以知道对面全死了
#include<bits/stdc++.h>
using namespace std;
#define LL long long
map<LL,double>M;
int bl[2][10];
bool End(LL a){
if(a<1000000)return 1;return 0;
}
LL ch(){
LL res=0;
for(int i=1;i<=6;i++)res*=10,res+=(LL)bl[1][i];
for(int i=1;i<=6;i++)res*=10,res+=(LL)bl[0][i];
return res;
}
double dfs(LL sta,int kill){
if(M.count(sta))return M[sta];
if(End(sta))return 1;
if(kill==0)return 0;
int sum=0;//people
for(int i=0;i<2;i++){
for(int j=1;j<=6;j++){
sum+=bl[i][j];
}
}
double ans=0;
for(int i=0;i<2;i++){
for(int j=1;j<=6;j++){
if(!bl[i][j])continue;
bl[i][j]--;
bl[i][j-1]++;
LL staNow=ch();
double res=dfs(staNow,kill-1);
bl[i][j]++;
bl[i][j-1]--;
M[staNow]=res;
ans+=(double)bl[i][j]/(double)sum*res;
}
}
return ans;
}
int main(){
int n,m,d;
scanf("%d%d%d",&n,&m,&d);
for(int i=1;i<=n;i++){
int tmp;
scanf("%d",&tmp);
bl[0][tmp]++;
}
for(int i=1;i<=m;i++){
int tmp;
scanf("%d",&tmp);
bl[1][tmp]++;
}
double ans=dfs(ch(),d);
printf("%.8f\n",ans);
}