题解 [美团 CodeM 初赛 Round B] 景区路线规划

有个影响因素k,显然不能高斯消元
n和k都不大,可以直接\(O(nk)\)跑DP
然而带上时间这一影响因素后的转移颇为难写,我从6点直接调到9点最后还是只能dfs爆搜骗了55pts
考场上推方程一定要冷静,调不对再把影响因素都看一遍
我考场上纠结的是\(dp[k][i]\)在什么时候应该继承\(dp[k+1][i]\)
然而考完再看发现根本不需要继承。。。
还是考虑从多个点向一个点转移:
\(dp[k][i]\)为还剩时间k时,在还剩时间k时经过第i个点次数的期望(实际上就是在第i个点时开心度的期望)
则转移就很显然了:\(dp[k][i] = \sum_{i->v}\frac{1}{cnt[v]}dp[k+c[i]+e.w][v]\)
然而这题还有一个坑点:题里没给边数范围
于是我就默认\(m\leq100\)了 成功RE
应该是不超过\(\frac{N*(N-1)}{2}\)条边

Code:

#include <bits/stdc++.h>
using namespace std;
#define N 110
#define ll long long 
//#define int long long 

inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

struct edge{int to, next, val;}e[N*(N-1)/2];
int n, m, k, K;
int head[N], size, cnt[500][N], c[N];
double dp[500][N], h1[N], h2[N];	// 0->小y	1->妹子
double ans1=0, ans2=0;

inline void add(int s, int t, int w) {edge *k=&e[++size]; k->to=t; k->next=head[s]; k->val=w; head[s]=size;}

int main()
{
	#ifdef DEBUG
	freopen("1.in", "r", stdin);
	#endif
	
	n=read(); m=read(); K=read();
	for (int i=1; i<=n; ++i) {c[i]=read(); h1[i]=1.0*read(); h2[i]=1.0*read();}
	for (int i=1,u,v,w; i<=m; ++i) {u=read(); v=read(); w=read(); add(u, v, w); add(v, u, w);}
	for (int i=1; i<=n; ++i) if (K>=c[i]) dp[K-c[i]][i] = 1.0/n;
	for (int k=K-1; k>=0; --k) {
		for (int i=1; i<=n; ++i) {
			if (k>K-c[i] || !dp[k][i]) continue;
			for (int j=head[i],v,t; j; j=e[j].next) {
				v=e[j].to; t=k-c[v]-e[j].val;
				if (t>=0) ++cnt[k][i];
			}
			if (cnt[k][i]) {
				for (int j=head[i],v,t; j; j=e[j].next) {
					v=e[j].to; t=k-c[v]-e[j].val;
					if (t>=0) dp[t][v] += dp[k][i]/cnt[k][i];
				}
			}
			//dp[k][i] += dp[k+1][i];
			ans1 += dp[k][i]*h1[i];
			ans2 += dp[k][i]*h2[i];
		}
	}
	
	#if 0
	for (int k=K; k>=0; --k) {
		cout<<setw(2)<<k<<' '; for (int i=1; i<=n; ++i) cout<<setw(4)<<dp[k][i]<<' '; cout<<endl;
		cout<<setw(2)<<k<<' '; for (int i=1; i<=n; ++i) cout<<setw(4)<<cnt[k][i]<<' '; cout<<endl;
	}
	#endif
	printf("%.5lf %.5lf\n", ans1, ans2);
	
	return 0;
}

posted @ 2021-05-29 15:27  Administrator-09  阅读(36)  评论(0编辑  收藏  举报