CodeForces 407B Long Path ( DP )

来源:互联网 发布:对网络教育的评价 编辑:程序博客网 时间:2024/05/21 19:41

题目大意:

有n+1个房间。从1-n个房间。每个房间有两扇门。一扇去i+1的房间另一扇去编号为pi的房间。问到达n+1的房间至少要走多少次

思路:

如果我没看美辰巨巨的博客。我也以为会是模拟。结果是DP。那我猜想应该是把到达下一个房间所需要的步数 + 前一次到达当前房间的步数

那么问题来了。DP数组应该怎么存放。

参考美辰巨巨的办法。DP存放的是从当前位置到达下一位置所需要的步数。然后在把DP数组走一遍即可以求出答案

另一种思路一直看不懂,被注释掉的部分

思路: 首先一个思考方法就是对比较小的样例进行纸上演算,了解题目的规律,看清本质。

不放p[i]=1;  i=1,2,3,4,5;

然后就发现每次都艰难的到了某一个点,又回到1,“无功而返”。

但是,找到了一些规律,每次第一次到达某一个点的时候,前面的全部是0(0-偶数,1-奇数),然后即将直接跳回到pi这个点,count(pi)==奇数。 然后又会历尽千辛万苦到了i,只是这一次,count(i)==偶数了,可以往前走了。

那么记f(i)代表第一次到i号结点的时候走的步数。 那么f(i+1)=f(i)+1(走到pi)+重新回到i的步数+1(向前走一步到i+1),重新回到i的步数,由于1,2,3...i-1,这些结点的count属性,和第一次到pi的时候是一样的,那么重新回到i的步数==f(i)-f(p[i]) .

然后地推公式就是f(i+1)=2*f(i)+2-f(p[i])  ,dp即可。

//  Created by Chenhongwei in 2015.//  Copyright (c) 2015 Chenhongwei. All rights reserved.#include "iostream"#include "cstdio"#include "cstdlib"#include "cstring"#include "climits"#include "queue"#include "cmath"#include "map"#include "set"#include "stack"#include "vector"#include "sstream"#include "algorithm"using namespace std;const int inf=1e8;const int maxn=1e5;const int mod=1e9+7;typedef long long ll;typedef unsigned long long ull;long long n,p[1010];long long dp[1010];int main(){//ios::sync_with_stdio(false);// freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);// cin>>n;// dp[1]=0;// for(int i=1;i<=n;i++)// {// cin>>p[i];// dp[i+1]=(2*dp[i]-dp[p[i]]+2+mod)%mod;// }// cout<<dp[n+1]<<endl;cin>>n;for(int i=1;i<=n;i++)cin>>p[i];dp[0]=0;for(int i=1;i<=n;i++){dp[i]=2;for(int j=p[i];j<i;j++)dp[i]=(dp[i]+dp[j])%mod;}ll ans=0;for(int i=1;i<=n;i++)ans=(ans+dp[i])%mod;cout<<ans<<endl;return 0;}



0 0
原创粉丝点击