hdu4362

/*
分析:
    优先队列+dp,思路同hdu4374。
    读完题后很快就想到了hdu4374的解法、也不负众望的轻松ok了。
    由于这个题不像hdu4374那样限制递推前后两个量的距离,所以可以不
用优先队列,既不需要每次从队列里面弹出极值、然后判断结果为可行才用
来递推;而是可以直接维护一个最值(代码中的mmin)、用O(1)的时间来直
接递推。时间复杂度O(n*m)。

                                                 2013-07-17
*/








#include"iostream"
#include"cstdio"
#include"queue"
#include"cstring"
using namespace std;
const int N=55;
const int M=1005;
const int inf=123456789;

int m,n,x;
struct node{
	int dis,dig,dp;
}E[N][M];

int min(int a,int b){
	return a>b?b:a;
}
int cmp(node n1,node n2){
	return n1.dis<n2.dis;
}

int main()
{
	int T;
	int i,l,j;
	int pre,mmin;
	cin>>T;
	while(T--)
	{
		cin>>m>>n>>x;
		for(i=0;i<=m;i++)
		for(l=1;l<=n;l++)
			E[i][l].dp=inf;

		E[0][1].dis=x;
		E[0][1].dp=0;
		sort(E[0]+1,E[0]+n+1,cmp);
		for(i=1;i<=m;i++)
		for(l=1;l<=n;l++)
			scanf("%d",&E[i][l].dis);
		for(i=1;i<=m;i++)
		for(l=1;l<=n;l++)
			scanf("%d",&E[i][l].dig);

		for(i=1;i<=m;i++)
		{
			pre=i-1;
			sort(E[i]+1,E[i]+n+1,cmp);

			j=1;
			mmin=inf;
			for(l=1;l<=n;l++)
			{
				while(j<=n && E[pre][j].dis<=E[i][l].dis)
				{
					if(E[pre][j].dp - E[pre][j].dis<mmin)
						mmin=E[pre][j].dp - E[pre][j].dis;
					j++;
				}
				E[i][l].dp=min(E[i][l].dp,mmin+E[i][l].dis + E[i][l].dig);
			}
			
			j=n;
			mmin=inf;
			for(l=n;l>=1;l--)
			{
				while(1<=j && E[pre][j].dis>=E[i][l].dis)
				{
					if(E[pre][j].dp + E[pre][j].dis<mmin)
						mmin=E[pre][j].dp + E[pre][j].dis;
					j--;
				}
				E[i][l].dp=min(E[i][l].dp,mmin-E[i][l].dis + E[i][l].dig);
			}
		}

		int ans=inf;
		for(l=1;l<=n;l++)	if(E[m][l].dp<ans)	ans=E[m][l].dp;
		cout<<ans<<endl;
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值