牛客跳跃游戏全家桶
跳跃游戏1
- 题目大意为给定一个长度为n的数组steps,数组[i]表示可以跳跃的最大范围,输出是否能跳到最后一个位置,能输出true,不能输出false。
- 题目思路:
- 一开始准备使用动态规划,dp[i]表示是否能跳到第i个位置。用i遍历1到n-1;j遍历0到i-1。如果steps[j]>=i-j(能从第j个位置走到第i个位置)&&dp[j]==true(第j个位置可达),则dp[i]=true;但是发现动态规划超时(正向动态规划)。
- 然后前看了一下题解,用一个maxsteps表示当前可以走到的最大位置,然后一直更新这个steps,如果当前位置小于等于maxsteps,说明可以走到当前位置,否则无论怎么样都无法走到当前位置,更别说走到最后一个位置了,所以立即输出false。当成功遍历完steps则成功走到最后一个位置,输出true。
代码
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n;
cin>>n;
vector<int> steps(n,0);
for(int i=0;i<n;i++){
cin>>steps[i];
}
vector<int> dp(n,false);
dp[0]=true;
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(i-j<=steps[j] && dp[j]==true){
dp[i]=true;
break;
}
}
}
if(dp.back()==true){
cout<<"true"<<endl;
}
else{
cout<<"false"<<endl;
}
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n;
cin>>n;
vector<int> steps(n,0);
for(int i=0;i<n;i++){
cin>>steps[i];
}
int maxsteps=steps[0];
for(int i=1;i<n;i++){
if(i>maxsteps ){
cout<<"false"<<endl;
return 0;
}
maxsteps=max(maxsteps,i+steps[i]);
}
cout<<"true"<<endl;
return 0;
}
跳跃游戏2
- 这道题在跳跃游戏1的基础上,求获取的最多的积分是多少,如果不能跳到最后一个位置,积分为-1。
- 解题思路:
- 因为要获取最大积分,则不能使用跳跃游戏1中的维护maxsteps的方法,因为这种方法不知道位置i到底是否哪个位置跳过来的,也就不能求得最大的积分。因此需要传统正向动态规划的方法,dp[i]表示跳到位置i能获得的最大积分,如果dp[i]==-1,则说明不能跳到dp[i],直接输出-1。但是提交上去发现居然又超时了!
- 反向推导:这样正向推时间复杂度太高,我们可以从位置i,推导它能到达的位置j的最大积分,这样的话时间复杂度低一点。dp[i]是跳到位置i能获得的最大积分,让j遍历i+1到i+nums[i],这是从位置i能跳到的范围,然后dp[j]=max(dp[j],dp[i]+nums[j])。
代码
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n;
cin>>n;
vector<int> nums(n,0);
for(int i=0;i<n;i++){
cin>>nums[i];
}
vector<long long> dp(n,-1);
dp[0]=nums[0];
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(i-j<=nums[j] ){
dp[i]=max(dp[i],dp[j]+nums[i]);
}
}
if(dp[i]==-1){
cout<<-1<<endl;
return 0;
}
}
cout<<dp.back()<<endl;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n;
cin>>n;
vector<int> nums(n,0);
for(int i=0;i<n;i++){
cin>>nums[i];
}
vector<long long> dp(n,0);
dp[0]=nums[0];
for(int i=0;i<n;i++){
for(int j=i+1;dp[i] && j<=i+nums[i] && j<n;j++){
dp[j]=max(dp[j],dp[i]+nums[j]);
}
}
if(dp.back()==0){
cout<<-1<<endl;
}
else{
cout<<dp.back()<<endl;
}
return 0;
}
跳跃游戏3
- 这次要求最少跳几次能跳到最后一个位置,真是傻逼。
- 解题思路:
- 正向的动态规划,dp[i]表示跳到位置i需要跳的最少次数,果不其然运行超时。
- 使用反向动态规划吧,和跳跃游戏2类似。
代码
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n;
cin>>n;
vector<int> nums(n,0);
for(int i=0;i<n;i++){
cin>>nums[i];
}
vector<long long> dp(n,INT32_MAX);
dp[0]=0;
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(i-j<=nums[j] ){
dp[i]=min(dp[i],dp[j]+1);
}
}
if(dp[i]==INT32_MAX){
cout<<-1<<endl;
return 0;
}
}
cout<<dp.back()<<endl;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n;
cin>>n;
vector<int> nums(n,0);
for(int i=0;i<n;i++){
cin>>nums[i];
}
vector<long long> dp(n,INT32_MAX);
dp[0]=0;
for(int i=0;i<n;i++){
for(int j=i+1; dp[i]!=INT32_MAX && j<=i+nums[i] && j<n ;j++){
dp[j]=min(dp[j],dp[i]+1);
}
}
if(dp.back()==INT32_MAX){
cout<<-1<<endl;
}
else{
cout<<dp.back()<<endl;
}
return 0;
}