您的位置:首页 > 其它

zoj 3469 区间dp **

2015-05-25 10:19 363 查看
题意:有一家快餐店送外卖,现在同时有n个家庭打进电话订购,送货员得以V-1的速度一家一家的运送,但是每一个家庭都有一个不开心的值,每分钟都会增加一倍,值达到一定程度,该家庭将不会再订购外卖了,现在为了以后有更多的家庭订购,要将外卖送到的情况下使得所有用户的不开心值总和达到最小

链接:点我

很明显,每多走一分钟,没送到的家庭的不开心值都会加倍,

假设是这样的顺序123X456,从X出发先往左右中间靠近的送,再往两边送省时间

dp[i][j][0]表示从i到j用户送到最小不开心值,此时送货员停留在左边即i位置

dp[i][j][1]表示从i到j用户送到最小不开心值,此时送货员停留在右边即j位置

核心是访问完区间i,j,那么区间内的一定访问过了,这是区间dp的显著特征

这题比较有意思

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
#define MOD 1000000007
const int INF=0x3f3f3f3f;
const double eps=1e-5;
typedef long long ll;
#define cl(a) memset(a,0,sizeof(a))
#define ts printf("*****\n");
const int MAXN=1005;
int n,m,tt;
int dp[MAXN][MAXN][2],a[MAXN],sum[MAXN],v,X;
struct Node
{
int x,b;
void in()
{
scanf("%d%d",&x,&b);
}
}node[MAXN];
bool cmp(Node a,Node c)
{
return a.x<c.x;
}
int main()
{
int i,j,k;
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
while(scanf("%d%d%d",&n,&v,&X)!=EOF)
{
for(i=1;i<=n;i++)   node[i].in();
n++;
node
.x=X,node
.b=0;
sort(node+1,node+1+n,cmp);
int st;
for(i=1;i<=n;i++)
{
if(node[i].x==X)
{
st=i;
break;
}
}
sum[1]=node[1].b;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
dp[i][j][0]=dp[i][j][1]=INF;
dp[st][st][0]=0,dp[st][st][1]=0;
for(i=2;i<=n;i++)
{
sum[i]=sum[i-1]+node[i].b;
}
for(i=st;i>=1;i--)
{
for(j=st;j<=n;j++)
{
if(i==j)    continue;//这个一定要加啊
dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(sum[i]+sum
-sum[j])*(node[i+1].x-node[i].x));
dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(sum[i]+sum
-sum[j])*(node[j].x-node[i].x));
dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(sum[i-1]+sum
-sum[j-1])*(node[j].x-node[i].x));
dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(sum[i-1]+sum
-sum[j-1])*(node[j].x-node[j-1].x));
}
}
printf("%d\n",v*min(dp[1]
[0],dp[1]
[1]));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: