1 条题解
-
0
思路
一道简单的 DP。
首先看数据范围是 ,我们便可以判断,这道题我们需要的时间复杂度是 或 。
再次回到题面,设节点 的左儿子和右儿子的宽度分别为 和 ,我们发现,当 在 的左子树中时,硬币向 节点移动这一步所需要花费的次数为 。
同时我们知道 总共需要经过的次数为 ,于是我们便可以从节点 往上一步步反推出从根节点到 所需的次数。具体代码过程
- dfs 查询节点 的位置。
- 在 dfs 回溯的过程中加上硬币从当前节点移动到下一个节点所需的次数(如果该连边的宽度小于 ,直接输出 )。
时间复杂度
节点数量为 ,最坏情况下每个节点经过一次,所以时间复杂度 。
AC 代码
码风不太好#include<bits/stdc++.h> using namespace std; const int N=1e5; long long n,v,lson[N+2][2],rson[N+2][2],flag,ans; void dp(long long now){ if(now==v){ flag=1,ans=1; return ; } if(lson[now][0]){ dp(lson[now][0]); if(flag){ if(lson[now][1]<ans){ cout<<"-1"; exit(0); } lson[now][1]-=ans; if(lson[now][1]<rson[now][1])ans=ans+rson[now][1]-lson[now][1]-1; return ; } } if(rson[now][0]){ dp(rson[now][0]); if(flag){ if(rson[now][1]<ans){ cout<<"-1"; exit(0); } rson[now][1]-=ans; if(rson[now][1]<=lson[now][1])ans=ans+lson[now][1]-rson[now][1]; } } return ; } int main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); cin>>n; for(int i=1;i<=n;i++)cin>>lson[i][0]>>lson[i][1]>>rson[i][0]>>rson[i][1]; cin>>v; dp(1); cout<<ans; return ( 0 - 0 ); }
- 1
信息
- ID
- 10335
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者