ZOJ Problem Set - 3469(区间dp)

//首先声明 本题思路代码都是抄袭大牛ZeroClock的


//思路: 例如  1 2 X 4 5
// 那么要给1 送饭必须先经过2 就是说必须先给内围的客人送饭 
// 那么dp的区间就要从中间往两边慢慢推进 则dp[i][j][0]表示服务员送完i到j这个区间的客户的饭停留在左边 所有客户不满意度的最小和
//                                        dp[i][j][1]表示服务员送完i到j这个区间的客户的饭停留在右边 所有客户不满意度的最小和


//服务员每给一个客户送饭 其他没得到饭的客户(除了i到j以外的客户)就会增加不满意度 这个不满意度也要算在当前的状态


#include<stdio.h>
#include<string.h>
#include<stdlib.h>


#define inf 1100000000 
#define N 1100


#define max(a,b)  ((a)>(b)?(a):(b))
#define debug 0


int sum[N],dp[N][N][2];
int n,v,x;


struct node
{
int x,v;
}arr[N];




int getadd(int a,int b)
{
return sum[b]-sum[a];
}


int min(int a,int b){return a<b?a:b;}


int cmp(const void *a,const void *b)
{
struct node *c;
struct node *d;
c=(struct node *)a;
d=(struct node *)b;
return c->x-d->x;
}


void init()
{
int i,j;


for(i=1;i<=n;i++)
{
scanf("%d%d",&arr[i].x,&arr[i].v);
}
arr[++n].x=x;
arr[n].v=0;


qsort(arr+1,n,sizeof(arr[0]),cmp);
for(i=1;i<=n;i++)
{
if(arr[i].x==x)
{
x=i;
break;
}
}
memset(sum,0,sizeof(sum));
for(i=1;i<=n;i++)
{
sum[i]=sum[i-1]+arr[i].v;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
dp[i][j][0]=dp[i][j][1]=inf;
}


int Dp()
{
int i,j,add;
dp[x][x][0]=dp[x][x][1]=0;





for(i=x;i>=1;i--)
{
for(j=x;j<=n;j++)
{
if(i==j) continue;
add=getadd(0,i-1)+getadd(j,n);//算出其他客户增加的不满意度


//送完饭后停在左边i处
dp[i][j][0]=min(dp[i][j][0],(dp[i+1][j][0]+(arr[i+1].x-arr[i].x)*(arr[i].v+add)));//从上个状态左边来
dp[i][j][0]=min(dp[i][j][0],(dp[i+1][j][1]+(arr[j].x-arr[i].x)*(add+arr[i].v)));//从上个状态右边来

if(debug)
printf("dp[i][j][0]:%d ",dp[i][j][0]);


//送完饭后停在右边j处
dp[i][j][1]=min(dp[i][j][1],(dp[i][j-1][0]+(arr[j].x-arr[i].x)*(add+arr[j].v)));//从上个状态左边在
dp[i][j][1]=min(dp[i][j][1],(dp[i][j-1][1]+(arr[j].x-arr[j-1].x)*(add+arr[j].v)));//从上个状态右边来
if(debug)
printf("dp[i][j][1]:%d ",dp[i][j][1]);
}
}
return min(dp[1][n][0],dp[1][n][1]);

}


int main()
{

while(scanf("%d%d%d",&n,&v,&x)!=EOF)
{
init();
int ans=Dp();
printf("%d\n",ans*v);//算时间的时候除以v^-1等于乘以v


}
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值