【问题描述】
Tom现在已经成为一个游戏里的重要人物。
这个游戏界面包含一行N个方格,N个方格用1到N的数字表示。Nikola开始是在1号位置,然后能够跳到其他的位置,Tom的第一跳必须跳到2号位置。随后的每一跳必须满足两个条件:
1.如果是向前跳,必须比前面一跳多跳一个方格。
2.如果是向后跳,必须和前面一跳一样远。
比如,在第一跳之后(当在2号位置时),Tom能够跳回1号位置,或者向前跳到4号位置。
每次他跳入一个位置,Tom必须支付相应的费用,Tom的目标是从1号位置尽可能便宜地跳到N号位置。
请你写一个程序,看看Tom跳到N号位置需要的最少花费是多少。
【输入格式】
输入一共有N+1行
第1行:包含一个整数N(2<=N<=1000),它是位置的数量
第2-N+1行:第i+1行表示第i个方格的费用,是一个正整数(不超过500)。
【输出格式】
输出一个参数,表示Tom跳到N号位置时需要的最少花费。
【输入样例1】 【输入样例2】
6 8
1 2 3 4 5 6 2 3 4 3 1 6 1 4
【输出样例1】 【输出样例2】
12 【2-1-3-6】 14 【2-4-7-4-8】
这道题楼楼第一反应就是回溯暴力……然后……华丽丽地70……【暴力不可取,但骗分很关键】
这道题正解就是DP,阶段性强和N的取值范围说明复杂度应该是O(n^2),所以想到DP就很简单了。
状态转移方程:从上个格子往前跳到当前第i格:f[ i ][ j ]=min( f[ i ][ j ], f[ i - j ][ j - 1 ]+value[ i ])
从上个格子向后跳到当前第i格:f[ i ][ j ]=min( f[ i ][ j ], f[i + j][ j ]+value[ i ])
最后对于所有的位于第n个格子的状态取min就是答案
下面是程序:
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+50,INF=0x3f3f3f3f;
int n,val[N],f[N][N];
using namespace std;
const int N=1e3+50,INF=0x3f3f3f3f;
int n,val[N],f[N][N];
int main()
{
cin>>n;
for(int i=1;i<=n;++i)
cin>>val[i];
memset(f,0x3f,sizeof(f));
f[1][0]=0;
for(int st=1;st<=n;++st)
{
for(int i=st+1;i<=n;++i)
f[i][st]=min(f[i][st],f[i-st][st-1]+val[i]);
for(int i=n-st;i>=1;--i)
f[i][st]=min(f[i][st],f[i+st][st]+val[i]);
}
int ans=INF;
for(int i=1;i<=n;++i)
{
ans=min(ans,f[n][i]);
}
cout<<ans;
return 0;
}
{
cin>>n;
for(int i=1;i<=n;++i)
cin>>val[i];
memset(f,0x3f,sizeof(f));
f[1][0]=0;
for(int st=1;st<=n;++st)
{
for(int i=st+1;i<=n;++i)
f[i][st]=min(f[i][st],f[i-st][st-1]+val[i]);
for(int i=n-st;i>=1;--i)
f[i][st]=min(f[i][st],f[i+st][st]+val[i]);
}
int ans=INF;
for(int i=1;i<=n;++i)
{
ans=min(ans,f[n][i]);
}
cout<<ans;
return 0;
}