典型的动规DP题
但是又和一般的DP有不同
这道题每次只可能有两个选择,那就是向右边走或者向左边走
而且,每次走完会有一个位置,这个位置一定是最左边或者最右边
开一个数组 DP[ i ][ j ][ x ] (X只取0或者1)
表示从i到 j 需要的最少油量 0表示到区间i点停止,1表示到区间j点停止
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10,inf=0x3f3f3f3f;
int dp[maxn][maxn][2];
int aw[maxn][maxn];
struct node
{
int d,w;
} LD[maxn];
int main()
{
int n,x,sum=0;
while(~scanf("%d%d",&n,&x))
{
sum=0;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&LD[i].d,&LD[i].w);
sum+=LD[i].w;
}
memset(dp,0,sizeof(dp));
memset(aw,0,sizeof(aw));
for(int i=1; i<=n; i++)
{
for(int j=i; j<=n; j++)
{
aw[i][j]=aw[i][j-1]+LD[j].w;
}
}
for(int i=x-1; i>=1; i--)
{
dp[i][x][0]=dp[i+1][x][0]+(sum-aw[i+1][x])*(LD[i+1].d-LD[i].d);
dp[i][x][1]=dp[i][x][0]+(sum-aw[i][x])*(LD[x].d-LD[i].d);
}
for(int i=x+1; i<=n; i++)
{
dp[x][i][1]=dp[x][i-1][1]+(sum-aw[x][i-1])*(LD[i].d-LD[i-1].d);
dp[x][i][0]=dp[x][i][1]+(sum-aw[x][i])*(LD[i].d-LD[x].d);
}
for(int i=x-1; i>=1; i--)
{
for(int j=x+1; j<=n; j++)
{
dp[i][j][0]=min(dp[i+1][j][0]+(sum-aw[i+1][j])*(LD[i+1].d-LD[i].d),dp[i+1][j][1]+(sum-aw[i+1][j])*(LD[j].d-LD[i].d));
dp[i][j][1]=min(dp[i][j-1][0]+(sum-aw[i][j-1])*(LD[j].d-LD[i].d),dp[i][j-1][1]+(sum-aw[i][j-1])*(LD[j].d-LD[j-1].d));
}
}
printf("%d\n",min(dp[1][n][0],dp[1][n][1]));
}
}