CSU 1725 加尔鲁什·地狱咆哮对阵虚灵大盗拉法姆(dp)

题意:x次攻击,加尔鲁什有y点血,z个三血奴隶主,然后奴隶主每受到一次非致命伤害就会再生出来一个奴隶主,场上最多7个奴隶主,问你最后打死加尔鲁什的概率是多少?

题解:dp递推咯,关键是状态怎么设计,开头没好好想,被金牌爷口胡了一句带歪到状压去了,其实这题状态根本不需要什么四进制状压,其实很简单

dp[攻击次数][加尔鲁什的剩余血量][三血奴隶主个数][二血个数][一血个数],因为数据范围特别小,所以怎么搞时间都很宽裕啊

然后最后答案就是所有0血状态相加

递推就是分类考虑场上有7个怪和不满7个怪的状态,然后转移就好了,唉这么简单的题我居然没有一下子想出来,dp还是太渣了,而且也太容易听别人的想法了。


#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")

using namespace std;
#define   MAX           200005
#define   MAXN          500005
#define   maxnode       105
#define   sigma_size    2
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
const double inf   = 1e18;
const double eps   = 1e-9;
const LL     mod   = 1e9+7;
const ull    mx    = 1e9+7;

/*****************************************************/
inline void RI(int &x) {
      char c;
      while((c=getchar())<'0' || c>'9');
      x=c-'0';
      while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/

double dp[21][21][10][10][10];

int main(){
    //freopen("test.txt","r",stdin);
    int t;
    cin>>t;
    while(t--){
        int x,y,z;
        cin>>x>>y>>z;
        mem(dp,0);
        dp[x][y][z][0][0]=1;
        double ans=0;
        for(int i=x-1;i>=0;i--){
            for(int j=1;j<=y;j++){
                for(int k=0;k<=7;k++){
                    for(int kk=0;kk<=7;kk++){
                        for(int kkk=0;kkk<=7;kkk++){
                            if(k+kk+kkk>7) break;
                            dp[i][j-1][k][kk][kkk]+=1.0/(k+kk+kkk+1)*dp[i+1][j][k][kk][kkk];
                            if(k+kk+kkk==7){
                                if(k) dp[i][j][k-1][kk+1][kkk]+=k*1.0/(k+kk+kkk+1)*dp[i+1][j][k][kk][kkk];
                                if(kk) dp[i][j][k][kk-1][kkk+1]+=kk*1.0/(k+kk+kkk+1)*dp[i+1][j][k][kk][kkk];
                                if(kkk) dp[i][j][k][kk][kkk-1]+=kkk*1.0/(k+kk+kkk+1)*dp[i+1][j][k][kk][kkk];
                            }
                            else{
                                if(k) dp[i][j][k][kk+1][kkk]+=k*1.0/(k+kk+kkk+1)*dp[i+1][j][k][kk][kkk];
                                if(kk) dp[i][j][k+1][kk-1][kkk+1]+=kk*1.0/(k+kk+kkk+1)*dp[i+1][j][k][kk][kkk];
                                if(kkk) dp[i][j][k][kk][kkk-1]+=kkk*1.0/(k+kk+kkk+1)*dp[i+1][j][k][kk][kkk];
                            }
                        }
                    }
                }
            }
        }
        for(int i=0;i<x;i++){
            for(int k=0;k<=7;k++){
                for(int kk=0;kk<=7;kk++){
                    for(int kkk=0;kkk<=7;kkk++) ans+=dp[i][0][k][kk][kkk];
                }
            }
        }
        printf("%.6f\n",ans);
    }
    return 0;
}



你可能感兴趣的:(CSU 1725 加尔鲁什·地狱咆哮对阵虚灵大盗拉法姆(dp))