题目链接:点击打开链接
题目思路:有点久没写区间dp了,居然在纠结选哪一个作为起点,被自己蠢死,对于这道题来说根本不用关心这个问题,因为区间dp本来就枚举了每一个从小到大的区间,想通这一点,剩下的就很无脑了,唯一需要学习的就是这里用滚动数组优化内存的方法,对于区间dp我们可以发现每一次转移都这跟上一次区间长度有关,也就是用区间长度的递增来递推的,那么就很容易知道前面的长度基本上没什么用了,所以可以用滚动数组,另外用滚动数组的时候还是不要用刷表法好。。不好处理
无滚动数组版本:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstring>
#include<iostream>
#include<sstream>
#include<cmath>
#include<vector>
#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
const int maxn = 1e7+6;
int dp[10000+5][10000+5][2];
int n,m;
int a[10000+5];
int b[10000+5];
int main()
{
while(~scanf("%d",&n)){
for(int i = 1;i<=n;i++){
scanf("%d%d",&a[i],&b[i]);
}
//memset(dp,INF,sizeof(dp));
for(int i = 1;i<=n;i++){
dp[i][i][0] = dp[i][i][1] = 0;
}
for(int len = 0;len<=n;len++){
for(int i = 1;i<=n;i++){
int j = i+len;
if(j>n)
continue;
if(i-1>=1){
dp[i-1][j][0] = min(dp[i][j][0]+a[i]-a[i-1],dp[i][j][1]+a[j]-a[i-1]);
if(dp[i-1][j][0]>=b[i-1])
dp[i-1][j][0] = INF;
// cout<<dp[i-1][j][0]<<' '<<i-1<<' '<<j<<endl;
}
if(j+1<=n){
dp[i][j+1][1] = min(dp[i][j][0]+a[j+1]-a[i],dp[i][j][1]+a[j+1]-a[j]);
if(dp[i][j+1][1]>=b[j+1])
dp[i][j+1][1] = INF;
// cout<<dp[i][j+1][1]<<' '<<i<<' '<<j+1<<endl;
}
}
}
int ans = min(dp[1][n][0],dp[1][n][1]);
if(ans==INF)
puts("No solution");
else
printf("%d\n",ans);
}
}
滚动数组版本:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstring>
#include<iostream>
#include<sstream>
#include<cmath>
#include<vector>
#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
const int maxn = 1e7+6;
int dp[10000+5][2][2];
int n,m;
int a[10000+5];
int b[10000+5];
int main()
{
while(~scanf("%d",&n)){
for(int i = 1;i<=n;i++){
scanf("%d%d",&a[i],&b[i]);
}
memset(dp,INF,sizeof(dp));
for(int i = 1;i<=n;i++){
dp[i][0][0] = dp[i][0][1] = 0;
}
int cur = 0;
for(int len = 1;len<n;len++){
cur ^=1;
for(int i = 1;i<=n-len;i++){
int j = i+len;
if(i+1<=n){
dp[i][cur][0] = min(dp[i+1][cur^1][0]+a[i+1]-a[i],dp[i+1][cur^1][1]+a[j]-a[i]);
if(dp[i][cur][0]>=b[i])
dp[i][cur][0] = INF;
}
// cout<<dp[i-1][j][0]<<' '<<i-1<<' '<<j<<endl
if(j-1>=0){
dp[i][cur][1] = min(dp[i][cur^1][0]+a[j]-a[i],dp[i][cur^1][1]+a[j]-a[j-1]);
if(dp[i][cur][1]>=b[j])
dp[i][cur][1] = INF;
}
// cout<<dp[i][j+1][1]<<' '<<i<<' '<<j+1<<endl
}
}
int ans = min(dp[1][cur][0],dp[1][cur][1]);
if(ans==INF)
puts("No solution");
else
printf("%d\n",ans);
}
}