Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits
Description
Lab与机关SERN展开了最后决战。
SERN派出了凶恶的FB,而Labmem们要捕获FB。
FB刚刚在第三水车厂露过行踪,Lab首领冈伦决定倾Lab之力全力追捕FB。
抓捕发生的地点可以表示成一张无向带权图,第三水车厂位于节点1。
冈伦仔细研究了FB的行为模式后得出以下结论:
首先,FB拥有极强的反跟踪能力,因此他深知不走回头路的重要性。他永远不会访问任何一个节点两次。
其次,FB行动以“速”著称,所以FB总是走最短路。亦即,FB访问任何一个节点时,走的路线都是从第三水车厂到该节点的最短路。这里保证从第三水车厂(节点1)到任意节点的最短路唯一。
第三,FB处于不停运动之中。亦即,只要有相邻的节点能满足前两条,他必然会移动。若有多个相邻节点可供选择,他会随机等概率选择一个作为他的移动目标。若没有节点满足这一要求,那么FB会跳世界线。而一旦FB跳世界线,Lab的这次行动很显然就意味着彻底失败。
冈伦分析出以上结论后决定,只能在节点上布置Labmem,实施埋伏抓捕。但是,FB的身体素质、格斗技术都十分优秀。因此,即使FB中伏,也有一定概率逃脱。当然,随着在此地埋伏的Labmem的数目的增多,逃脱几率会减小。如果逃脱成功,FB会像什么都没发生一样,继续按上文所述的原则行动。
注意,FB一旦到达某个节点,埋伏在该处的Labmem会立即行动,只有FB逃脱了当前节点的抓捕后才能进行下一步行动(继续移动或跳世界线),包括节点1,也就是说FB需要先逃脱节点1的埋伏才能进行他的第一次行动。
现在冈伦已经知道各节点设置不同数量的Labmem能成功抓捕FB的概率,现在冈伦想要使得抓捕成功的概率最大。
Input
输入文件第一行包含两个数N,M,分别表示节点数和边数。
接下来M行,每行3个数u,v,w,表示节点u和v之间有一条权值为w的无向边。
接下来一个数S,表示可以参与埋伏的Labmem成员总数。
接下来N行,每行S个数,第i行第j个数Pij表示在节点i埋伏j个Labmem抓捕成功的概率。注意,如果不埋伏任何Labmem,那么显然绝不可能捕获FB。
Output
输出文件仅包含一个实数,保留4位小数,表示最大捕获概率。
Sample Input
4 4 1 2 1 1 3 2 2 4 3 3 4 1 2 0.01 0.1 0.5 0.8 0.5 0.8 0.7 0.9
Sample Output
0.6000
Data Constraint
对于20%的数据,N,S<=6
对于50%的数据,N,S<=30,每个节点度数不大于3
对于100%的数据,N,S<=200,M<=20000,1<=a,b<=N,1<=c<=10000,
0
Source / Author: 常州高级中学 catch
思路:
先把最短路树建出来。
在树上dp。
设f[i][j]为以i为根的子树中选j个Labmem的最大抓捕机率。
对于当前做到的节点i,先处理出它的儿子的f,再将它儿子的状态合并到f[i].(此时默认i节点不放)
最后,枚举i点放几个,转移见标。
#include
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define N 210
#define rint register int
#define M 40010
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
#define INF 2147483647
using namespace std;
struct edge
{int v,fr,d;};
int tot,tail[N] ; edge e[M*2];
int n,m,s,i,j,len;
double ans;
int f[N],pre[N],l[N*500],q[N];
double pro[N],g[N][N],P[N][N];
void init()
{
mem(f,127);
int i=0,j=1;
f[1]=0;
l[1]=1;
while(i++=1;j--)
{
for(k=j;k>0;k--) //x
g[x][j] = max(g[x][j] , g[x][j-k] + g[v][k]/(double)son );
}
}
}
for(j=s;j>0;j--)
{
for(k=j;k>0;k--)
g[x][j] = max(g[x][j] , P[x][k] + (1.00-P[x][k]) * g[x][j-k]);
}
return ;
}
void add(int u,int v,int d)
{
e[++tot].v=v;
e[tot].fr=tail[u];
e[tot].d=d;
tail[u]=tot;
}
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
int u,v,d;
scanf("%d%d%d",&u,&v,&d);
add(u,v,d),add(v,u,d);
}
scanf("%d",&s);
for(i=1;i<=n;i++)
for(j=1;j<=s;j++)scanf("%lf",&P[i][j]);
ans=0.00;
init();// f
mem(g,0);
dfs(1);
ans = g[1][s];
printf("%.4lf",ans);
return 0;
}