3640: JC的小苹果 - BZOJ

让我们继续JC和DZY的故事。
“你是我的小丫小苹果,怎么爱你都不嫌多!”
“点亮我生命的火,火火火火火!”
话说JC历经艰辛来到了城市B,但是由于他的疏忽DZY偷走了他的小苹果!没有小苹果怎么听歌!他发现邪恶的DZY把他的小苹果藏在了一个迷宫里。JC在经历了之前的战斗后他还剩下hp点血。开始JC在1号点,他的小苹果在N号点。DZY在一些点里放了怪兽。当JC每次遇到位置在i的怪兽时他会损失Ai点血。当JC的血小于等于0时他就会被自动弹出迷宫并且再也无法进入。
但是JC迷路了,他每次只能从当前所在点出发等概率的选择一条道路走。所有道路都是双向的,一共有m条,怪兽无法被杀死。现在JC想知道他找到他的小苹果的概率。

输入格式:
第一行三个整数表示n,m,hp。接下来一行整数,第i个表示jc到第i个点要损失的血量。保证第1个和n个数为0。接下来m行每行两个整数a,b表示ab间有一条无向边。

输出格式:
仅一行,表示JC找到他的小苹果的期望概率,保留八位小数。

样例输入:
3 3 2 0 1 0 1 2 1 3 2 3

样例输出:
0.87500000

数据范围:
对于10%的数据n=5,hp=1
对于30%的数据n<=20,hp<=5
对于60%的数据n<=50,hp<=10000
对于另外10%的数据 所有点权均为正
对于100%的数据 2<=n<=150,hp<=10000,m<=5000,保证图联通,点权非负。

时间限制:
4s

空间限制:
256M

囧,一开始不知道点权非负,是后来加上去的,问别人才知道

copy题解(懒得写了,题解讲得比我好多了):

【算法一】
爆搜(虽然我也不知道怎么搜) 期望的分10
【算法二】
把所有点按照hp拆点,然后高斯消元,复杂度O(hp^3*n^3)。期望的分30
【算法三】
我们发现对于hp来说层与层之间是DAG,所以每一层做高斯消元。然后层与层之间递推就可以了。复杂度O(hp*n^3),期望的分60
【算法四】
大致同算法三,但是我们发现每一次高斯消元的矩阵除了常数项都是相同的,所以可以先进行一次高斯消元预处理,其它只要做带入的工作即可。复杂度O(hp*n^2),期望的分100

囧,自环环太无语,只能加一条,不能加两次

 const
maxn=;
maxm=;
maxhp=;
eps=1e-9;
var
x,y:array[..maxn,..maxn]of double;
f:array[..maxhp,..maxn]of double;
ff:array[..maxn]of double;
a,d,first:array[..maxn]of longint;
last,next:array[..maxm*]of longint;
n,m,hp,tot:longint;
ans:double; procedure insert(x,y:longint);
begin
if x=n then exit;
inc(tot);
last[tot]:=y;
next[tot]:=first[x];
first[x]:=tot;
inc(d[x]);
end; procedure swap(var x,y:double);
var
t:double;
begin
t:=x;x:=y;y:=t;
end; procedure work;
var
i,j,k:longint;
s:double;
begin
for i:= to n do
begin
j:=first[i];
while j<> do
begin
if a[last[j]]= then x[last[j],i]:=x[last[j],i]-/d[i];
j:=next[j];
end;
end;
for i:= to n do x[i,i]:=x[i,i]+;
for i:= to n do y[i,i]:=;
for i:= to n- do
begin
for j:=i to n do
if abs(x[j,i])>eps then break;
for k:= to n do swap(x[i,k],x[j,k]);
for k:= to n do swap(y[i,k],y[j,k]);
for j:=i+ to n do
if abs(x[j,i])>eps then
begin
s:=x[j,i]/x[i,i];
for k:= to n do x[j,k]:=x[j,k]-x[i,k]*s;
for k:= to n do y[j,k]:=y[j,k]-y[i,k]*s;
end;
end;
for i:=n downto do
for j:= to i- do
if abs(x[j,i])>eps then
begin
s:=x[j,i]/x[i,i];
for k:= to n do x[j,k]:=x[j,k]-x[i,k]*s;
for k:= to n do y[j,k]:=y[j,k]-y[i,k]*s;
end;
for i:= to n do
for j:= to n do
y[i,j]:=y[i,j]/x[i,i];
end; procedure main;
var
i,j,k,u,v:longint;
begin
read(n,m,hp);
for i:= to n do read(a[i]);
for i:= to m do
begin
read(u,v);
if u<>v then insert(u,v);
insert(v,u);
end;
work;
f[hp,]:=;
for i:=hp downto do
begin
ff:=f[i];
ans:=ans+ff[n];ff[n]:=;
for j:= to n do f[i,j]:=;
for j:= to n do
for k:= to n do
f[i,j]:=f[i,j]+ff[k]*y[j,k];
ans:=ans+f[i,n];f[i,n]:=;
for j:= to n do
begin
k:=first[j];
while k<> do
begin
if (i-a[last[k]]>) and (a[last[k]]>) then
f[i-a[last[k]],last[k]]:=f[i-a[last[k]],last[k]]+f[i,j]/d[j];
k:=next[k];
end;
end;
end;
writeln(ans::);
end; begin
main;
end.

更新:bzoj上有了题目,但是pascal一直被卡,想了n久,无奈交了std(C++的),突然又想到一个优化,15s+卡过了(好辛酸啊)

上一篇:抛弃jQuery:DOM API之操作元素


下一篇:Basics of Map Algebra