題鏈:
題解:
期望dp,高斯消元
設dp[i][h]在i位置且血量為h這個狀態的期望經過次數。
因為每當到達n點就停止遊戲,所以到達終點的概率就是dp[n][1]+dp[n][2]+...+dp[n][hp]
可以按血量把dp分成若干個層次,我們希望這樣分層次後就可以把問題轉變為dag上的dp,
可是存在傷害值為0的點,所以我們對於每一層列出來的n的dp計算式,是可能存在環的。
所以要用高斯消元。複雜度(hp*n^3)
注意到在每個層次做高斯消元時,其實這些方程的係數都相同,
(規定一下方程的形式:a1*x1+a2*x2+a3*x3+...+an*xn=c,a都為係數,x為n個未知數,c為常數項)
所以我們可以預處理記錄下高斯消元是怎麼消的,或者說,
因為每個未知數一定是由n個常數項線性組合起來的,所以我們記錄一下每個未知數是如何由n個方程的常數項構成的
具體做法是把n個常數項看成乙個1×n的x矩陣,然後把每個未知數xi分別也看成1×n的乙個矩陣yi
然後如果知道了常數項的矩陣,就可以由yi*x的倒置矩陣得到乙個1×1的矩陣,而裡面存的值就是xi的值。
所以高斯消元就是去求出這n個yi矩陣。
複雜度:o(hp*n^2+n^3)
更詳細的膜這裡:
**:
#include#define maxn 160using namespace std;
const double eps=1e-12;
double ans,a[maxn][maxn],*a[maxn],dp[maxn][10005];
int damage[maxn],cnt[maxn];
int n,m,hp;
int dcmp(double x)
struct edge
void adde(int u,int v)
}e;struct matrix
matrix operator - () const
matrix operator + (const matrix &rtm) const
matrix operator - (const matrix &rtm) const
matrix operator * (const double k) const
matrix operator & (const matrix &rtm) const
matrix operator / (const double k) const
}b[maxn],c[maxn],x;
matrix *c[maxn];
void buildequation()
} for(int i=1;i<=n;i++)
}void gausselimination(int pos,int i)
if(dcmp(a[pos][i])!=0)
for(int j=pos+1;j<=n;j++)
gausselimination(pos+(dcmp(a[pos][i])!=0),i+1);
if(dcmp(a[pos][i])!=0)
}int main()
buildequation();
gausselimination(1,1);
for(int h=hp;h>=1;h--)
} if(h==hp) x.a[1][1]-=1;
for(int i=1;i<=n;i++)
dp[i][h]=(b[i]&x).a[1][1];
ans+=dp[n][h];
} cout
}
BZOJ3640 JC的小蘋果
建分層圖,有怪獸的點連後邊的層,每層之間是有拓撲序的所以可以一層一層高斯消元,然後我們發現每一層的方程組係數是一樣的只有常數不一樣,而常數項不影響消元過程,所以我們可以預處理消元的過程,這樣每次只需要消常數項就是n 2的,總複雜度就是hp n 2 這個 有重邊和自環,非常的蛋疼 include in...
BZOJ 3640 JC的小蘋果
我們考慮列出期望方程組,dp i j 表示在第 i 個點血量為 j 的時候到達 n 點的概率,所有的 dp n j 都是1,所有 j 0 都是0 答案是 dp 1 hp dp u j sum fracdp v j a v 我們發現這個方程在j不同的時候,只有常數項發生改變,剩下的係數不變 於是我們把...
BZOJ 3640 JC的小蘋果(逆矩陣)
題意 給出乙個無向圖,從1走到n。開始是血量h,從u到達v時血量減少a v 每次走每條路徑的概率相等。求走到n且血量大於0的概率。思路 設f h u 表示到達u血量為h的概率。由於有的點到達時不掉血,這個不好弄。列出方程組,求出每個不掉血的點由哪些點到達以及他們的係數。比如x,y,z可到達r,r點不...