题意:有一家快餐店送外卖,现在同时有n个家庭打进电话订购,送货员得以V-1的速度一家一家的运送,但是每一个家庭都有一个不开心的值,每分钟都会增加一倍,值达到一定程度,该家庭将不会再订购外卖了,现在为了以后有更多的家庭订购,要将外卖送到的情况下使得所有用户的不开心值总和达到最小
链接:点我
很明显,每多走一分钟,没送到的家庭的不开心值都会加倍,
假设是这样的顺序123X456,从X出发先往左右中间靠近的送,再往两边送省时间
dp[i][j][0]表示从i到j用户送到最小不开心值,此时送货员停留在左边即i位置
dp[i][j][1]表示从i到j用户送到最小不开心值,此时送货员停留在右边即j位置
核心是访问完区间i,j,那么区间内的一定访问过了,这是区间dp的显著特征
这题比较有意思
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 typedef long long ll; 13 #define cl(a) memset(a,0,sizeof(a)) 14 #define ts printf("***** "); 15 const int MAXN=1005; 16 int n,m,tt; 17 int dp[MAXN][MAXN][2],a[MAXN],sum[MAXN],v,X; 18 struct Node 19 { 20 int x,b; 21 void in() 22 { 23 scanf("%d%d",&x,&b); 24 } 25 }node[MAXN]; 26 bool cmp(Node a,Node c) 27 { 28 return a.x<c.x; 29 } 30 int main() 31 { 32 int i,j,k; 33 #ifndef ONLINE_JUDGE 34 freopen("1.in","r",stdin); 35 #endif 36 while(scanf("%d%d%d",&n,&v,&X)!=EOF) 37 { 38 for(i=1;i<=n;i++) node[i].in(); 39 n++; 40 node[n].x=X,node[n].b=0; 41 sort(node+1,node+1+n,cmp); 42 int st; 43 for(i=1;i<=n;i++) 44 { 45 if(node[i].x==X) 46 { 47 st=i; 48 break; 49 } 50 } 51 sum[1]=node[1].b; 52 for(i=1;i<=n;i++) 53 for(j=1;j<=n;j++) 54 dp[i][j][0]=dp[i][j][1]=INF; 55 dp[st][st][0]=0,dp[st][st][1]=0; 56 for(i=2;i<=n;i++) 57 { 58 sum[i]=sum[i-1]+node[i].b; 59 } 60 for(i=st;i>=1;i--) 61 { 62 for(j=st;j<=n;j++) 63 { 64 if(i==j) continue;//这个一定要加啊 65 dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(sum[i]+sum[n]-sum[j])*(node[i+1].x-node[i].x)); 66 dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(sum[i]+sum[n]-sum[j])*(node[j].x-node[i].x)); 67 dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(sum[i-1]+sum[n]-sum[j-1])*(node[j].x-node[i].x)); 68 dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(sum[i-1]+sum[n]-sum[j-1])*(node[j].x-node[j-1].x)); 69 } 70 } 71 printf("%d ",v*min(dp[1][n][0],dp[1][n][1])); 72 } 73 }