题意:
告诉你n 个点位置和消失的时间,你可以从任意一个点出发,求出到达所有点的最小时间?
思路:
区间dp
令dp[i][j][0] 你在i~j 这个区间的i 位置。
dp[i][j][1] 表示你在i~j 这个区间的j 位置。
转移的话 一个长度为k 的区间只能有长度为k-1的区间转移得到:
吐槽:
第一遍超时 写的记忆话搜索, 改成递推式后 可以免掉初始化这一步。这样就快了很多了。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e4+1;
int dp[maxn][maxn][2];
const int inf = 0x3f3f3f3f;
int a[maxn], t[maxn];
int aaa(int x){
if (x < 0) return -x;
return x;
}
int main(){
int n;
while(~scanf("%d",&n) ){
for (int i = 1; i <= n; ++i){
scanf("%d %d",a+i, t+i);
}
for (int i = n; i >= 1; --i){
for (int j = i; j <= n; ++j){
if (i == j) dp[i][j][0] = dp[i][j][1] = 0;
else{
dp[i][j][0] = min(dp[i+1][j][0] + aaa(a[i+1]-a[i]), dp[i+1][j][1] + aaa(a[j]-a[i]));
if (dp[i][j][0] >= t[i])dp[i][j][0] = inf;
dp[i][j][1] = min(dp[i][j-1][0] + aaa(a[j]-a[i]), dp[i][j-1][1] + aaa(a[j]-a[j-1]));
if (dp[i][j][1] >= t[j])dp[i][j][1] = inf;
}
}
}
int ans = min(dp[1][n][0],dp[1][n][1]);
if (ans >= inf) puts("No solution");
else printf("%d\n",ans);
}
return 0;
}