没想到还会回来写博客,算是回忆下把,来一道区间dp基础题。
题意:一个送外卖的从某个出发点送外卖,但是每个顾客地点都有一个不满意值,会随着时间每秒增加b[i],每个顾客地点都有一个距离,可以人为是在x轴上的坐标。现在问如何送外卖使得不满意度最小。
题解:好像做过,不过这次换了一个更优美的姿势过,记忆优化写起来会比较好写,而且姿势优美。
dp[i][j][pos]表示[l,r]区间的顾客都送完了现在位于pos位置,pos==0表示在左边,pos==1表示在右边。
每次可以选择往区间左端或这右端走。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll INF = 0x3f3f3f3f3f3f3f3f; const int maxn = 1005; ll dp[maxn][maxn][2]; int vis[maxn][maxn][2]; ll sum[maxn]; struct Node{ int x,b; }a[maxn]; int n, X, V; void cmin(ll& a,ll b){ if(b < a) a = b; } ll dfs(int l,int r,int pos){ if(l==1 && r==n) return 0; if(vis[l][r][pos]) return dp[l][r][pos]; ll res=INF; int cost = sum[n]-sum[r] + sum[l-1] - sum[0]; if(pos==0){ if(l-1>=1) cmin(res, dfs(l-1,r,0) + (a[l].x-a[l-1].x)*cost); if(r+1<=n) cmin(res, dfs(l,r+1,1) + (a[r+1].x-a[l].x)*cost); } else{ if(l-1>=1) cmin(res, dfs(l-1,r,0) + (a[r].x-a[l-1].x)*cost); if(r+1<=n) cmin(res, dfs(l,r+1,1) + (a[r+1].x-a[r].x)*cost); } vis[l][r][pos]=1; return dp[l][r][pos]=res; } bool cmp(const Node& n1, const Node& n2){ return n1.x<n2.x; } int main(){ //freopen("read.txt","r",stdin); int pos; while(scanf("%d%d%d",&n,&V,&X)!=EOF){ for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].b); a[++n].x=X; a[n].b=-1; sort(a+1,a+1+n,cmp); for(int i=1;i<=n;i++){ if(a[i].x==X && a[i].b==-1) pos=i; sum[i]=sum[i-1]+a[i].b; } memset(vis,0,sizeof vis); memset(dp,-1,sizeof dp); printf("%lld\n",min(dfs(pos,pos,0),dfs(pos,pos,1))*V); } return 0; }