P1685 游览

· · 题解

前言:

绿题就是绿题,做出来也得十几分钟。

看一下居然是最优解!

Problem。

最优解提交记录。

思路和代码:

首先我就想到了动态规划:

dp_{i1} 表示起点到 i 点总共需要花费的。

dp_{i0} 表示起点到 i 点的总方案数。

说句题外话:我首先没想到要搞方案数,死了五分钟。

则如果从 x 走到 y 而且他们之间代价为 money 可得出:

$dp_{y1}=dp_{y1}+dp_{x1}+dp_{x0}\times money$。 第一个很简单理解,这是因为方案数为累加,运用加法原理。 第二个是将两点的总价值相加,再加上方案数乘上代价,这是因为一共有方案数个方案,这条线也需走方案数个,需相乘再相加。 于是愉快地得出错误代码: ```c++ //20pts //luogu P1685 #include<bits/stdc++.h> using namespace std; const int N=1e4+5; int dp[N][2],n,m,qi,zh,p; struct DO { int next; int to; int money; }; const int maxn=5e4+5; DO a[maxn]; int head[maxn],cnt=1; void add(int x,int y,int sum) { a[cnt].to=y; a[cnt].money=sum; a[cnt].next=head[x]; head[x]=cnt++; } void DP(int x) { for(int i=head[x];i;i=a[i].next) { int y=a[i].to; dp[y][0]=(dp[x][0]+dp[y][0])%10000; dp[y][1]=(dp[y][1]+dp[x][1]+dp[x][0]*a[i].money)%10000; DP(y); } } int main() { cin.tie(0);cout.tie(0); cin>>n>>m>>qi>>zh>>p; for(int i=1;i<=m;i++) { int x,y,sum; cin>>x>>y>>sum; add(x,y,sum); } dp[qi][0]=1; DP(qi); cout<<((dp[zh][0]-1)*p+dp[zh][1])%10000; } ``` 绿+红+黑。 我们发现,直接搜到这点继续往下搜有可能信息不全,会错误,而且搜那么多次,很显然会超时,为了预防这些,我们可以记录点的入度,如果入读为零即可安心往下搜。 于是我们修改函数和输入,得出最优解: ``` //100pts //luogu P1685 //最优解(用快读+关闭输出流的cout #include<bits/stdc++.h> using namespace std; const int N=1e4+5; int dp[N][2],n,m,qi,zh,p; int in[N]; struct DO { int next; int to; int money; }; typedef int LL; inline LL read() { register LL x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar(); return x*f; } const int maxn=5e4+5; DO a[maxn]; int head[maxn],cnt=1; void add(int x,int y,int sum) { a[cnt].to=y; a[cnt].money=sum; a[cnt].next=head[x]; head[x]=cnt++; } void DP(int x) { for(int i=head[x];i;i=a[i].next) { int y=a[i].to; dp[y][0]=(dp[x][0]+dp[y][0])%10000; dp[y][1]=(dp[y][1]+dp[x][1]+dp[x][0]*a[i].money)%10000; in[y]--; if(!in[y])DP(y); } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); n=read(),m=read(),qi=read(),zh=read(),p=read(); for(int i=1;i<=m;i++) { int x,y,sum; x=read(),y=read(),sum=read(),in[y]++; add(x,y,sum); } dp[qi][0]=1; DP(qi); cout<<((dp[zh][0]-1)*p+dp[zh][1])%10000; } ``` 如果觉得这个有用,那就点赞顶这篇题解,谢谢!