ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 变异大老鼠

2021-10-07 20:03:37  阅读:186  来源: 互联网

标签:老鼠 变异 题解 long int sec dis 节点 define


传送门

大水题,spt上直接背包即可,但我因为太弱爆零了

  • 树上背包当出现在每个点有概率终止DP(举个例子:从点1逃跑,在每个点有概率被抓捕)的情况时:
    特别注意在当前节点的容量与字节点的容量是独立的,不能像子树合并一样直接把当前节点的dp值揉进去
    否则无法正确统计从当前节点进入下层节点的概率
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define db double
#define fir first
#define sec second
#define make make_pair
//#define int long long

int n, m, k;
int back[N], cnt[N];
ll dis[N];
db p[310][310];
bool vis[N];
priority_queue<pair<ll, int>> q;
namespace edge1{
	int head[N], size;
	struct edge{int to, next, val;}e[N<<1];
	inline void add(int s, int t, int w) {e[++size].to=t; e[size].val=w; e[size].next=head[s]; head[s]=size;}
}
namespace edge2{
	int head[N], size;
	struct edge{int to, next;}e[N<<1];
	inline void add(int s, int t) {e[++size].to=t; e[size].next=head[s]; head[s]=size;}
}

void init() {
	using namespace edge1;
	memset(dis, 0x3f, sizeof(dis));
	dis[1]=0;
	q.push(make(0, 1));
	pair<ll, int> u;
	while (q.size()) {
		u=q.top(); q.pop();
		if (vis[u.sec]) continue;
		vis[u.sec]=1;
		for (int i=head[u.sec],v; ~i; i=e[i].next) {
			v = e[i].to;
			if (dis[u.sec]+e[i].val < dis[v]) {
				dis[v]=dis[u.sec]+e[i].val; back[v]=u.sec;
				q.push(make(-dis[v], v));
			}
		}
	}
	for (int i=2; i<=n; ++i) edge2::add(back[i], i), ++cnt[back[i]];
}

namespace force{
	int num[N];
	db ans;
	db dfs2(int u) {
		using namespace edge2;
		db sum=p[u][num[u]];
		db ps=1.0/cnt[u];
		for (int i=head[u],v; ~i; i=e[i].next) {
			v = e[i].to;
			sum+=ps*dfs2(v);
		}
		return sum;
	}
	void dfs1(int u, int rest) {
		if (u>n) {
			if (rest==0) ans=max(ans, dfs2(1));
			return ;
		}
		for (int i=0; i<=rest; ++i) {
			num[u]=i;
			dfs1(u+1, rest-i);
		}
	}
	void solve() {
		dfs1(1, k);
		printf("%.6lf\n", min(ans, 1.0));
		exit(0);
	}
}

namespace task1{
	db dp[310][30010], tem[310][30010];
	void dfs(int u) {
		using namespace edge2;
		// cout<<"dfs: "<<u<<' '<<cnt[u]<<endl;
		for (int i=1; i<=k; ++i) dp[u][i]=p[u][i];
		db ps=cnt[u]?(1.0/cnt[u]):1.0;
		// cout<<"ps: "<<u<<' '<<ps<<endl;
		for (int i=head[u],v; ~i; i=e[i].next) {
			v = e[i].to;
			dfs(v);
			for (int s=k; ~s; --s) {
				for (int t=k-s; ~t; --t) {
					tem[u][s+t]=max(tem[u][s+t], tem[u][s]+ps*dp[v][t]);
				}
			}
		}
		for (int s=k; ~s; --s) {
			for (int t=k-s; ~t; --t) {
				dp[u][s+t]=max(dp[u][s+t], dp[u][s]+(1-dp[u][s])*tem[u][t]);
			}
		}
	}
	void solve() {
		dfs(1);
		printf("%.6lf\n", min(dp[1][k], 1.0));
		// cout<<"---dp---"<<endl;
		// for (int i=1; i<=n; ++i) {for (int j=1; j<=k; ++j) printf("%.3lf ", dp[i][j]); cout<<endl;}
		exit(0);
	}
}

signed main()
{
	freopen("arrest.in", "r", stdin);
	freopen("arrest.out", "w", stdout);

	using namespace edge1;
	memset(edge1::head, -1, sizeof(edge1::head));
	memset(edge2::head, -1, sizeof(edge2::head));
	scanf("%d%d%d", &n, &m, &k);
	for (int i=1,x,y,z; i<=m; ++i) {
		scanf("%d%d%d", &x, &y, &z);
		add(x, y, z); add(y, x, z);
	}
	for (int i=1; i<=n; ++i) for (int j=1; j<=k; ++j) scanf("%lf", &p[i][j]);
	init();
	task1::solve();

	return 0;
}

标签:老鼠,变异,题解,long,int,sec,dis,节点,define
来源: https://www.cnblogs.com/narration/p/15376810.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有