POJ1991 Turning in Homework 贪心+动态规划

贪心+ 动态规划。

贪心思想:当有一段连续区间[i,j]未交时,取i或j是最优的。

贪心思想证明:如果在[i,j]这段连续区间都没有被取的时候取了中间的m,那么后来一定要从m返回到i或者j,这时候是一定走了“冤枉路的”。而如果这时取了i或者j,那么到中间的时候m一定可以取。证毕。

动态规划的方程这时候就简单了:

f[i,j,0]表示[i+1,j]这一段连续区间都没有取,奶牛站在i上

f[i,j,1]表示[i,j-1]这一段连续区间都没有取,奶牛站在j上

方程:

f[i,k,0]:=Min(Max(f[i-1,k,0]+a[i]-a[i-1],time[i]),Max(f[i,k+1,1]+a[k+1]-a[i],time[i]));

f[i,k,1]:=Min(Max(f[i-1,k,0]+a[k]-a[i-1],time[k]),Max(f[i,k+1,1]+a[k+1]-a[k],time[k]));

其中,k=n,或者i=1的情况要特判一下,否则会越界。

CODE

Program POJ1991;//By_Poetshy
Const
	maxn=1000;
Var
	i,j,k,m,n,b,ans,tmp				:Longint;
	time,a							:Array[1..maxn]of Longint;
	f								:Array[1..maxn,1..maxn,0..1]of Int64;
	
Function Max(i,j:Int64):Int64;
begin
	if i>j then exit(i);exit(j);
end;
	
Function Min(i,j:Int64):Int64;
begin
	if i<j then exit(i);exit(j);
end;

Procedure Qsort(l,r:Longint);
var i,j,k,temp:Longint;
begin
	i:=l;j:=r;
	k:=a[(i+j)>>1];
	repeat
		while a[i]<k do inc(i);
		while a[j]>k do dec(j);
		if i<=j then
			begin
				temp:=a[i];a[i]:=a[j];a[j]:=temp;
				temp:=time[i];time[i]:=time[j];time[j]:=temp;
				inc(i);dec(j);
			end;
	until i>j;
	if i<r then Qsort(i,r);
	if l<j then Qsort(l,j);
end;

BEGIN
	readln(n,m,b);
	for i:=1 to n do readln(a[i],time[i]);
	Qsort(1,n);
	f[1,n,0]:=Max(time[1],a[1]);f[1,n,1]:=Max(time[n],a[n]);
	for j:=n-2 downto 0 do
		for i:=1 to n-j do
			begin
				k:=i+j;
				if k=n then
					begin
						f[i,k,0]:=Max(f[i-1,k,0]+a[i]-a[i-1],time[i]);
						f[i,k,1]:=Max(f[i-1,k,0]+a[k]-a[i-1],time[k]);
					end else if i=1 then
						begin
							f[i,k,0]:=Max(f[i,k+1,1]+a[k+1]-a[i],time[i]);
							f[i,k,1]:=Max(f[i,k+1,1]+a[k+1]-a[k],time[k]);
						end else
							begin
								f[i,k,0]:=Min(Max(f[i-1,k,0]+a[i]-a[i-1],time[i]),Max(f[i,k+1,1]+a[k+1]-a[i],time[i]));
								f[i,k,1]:=Min(Max(f[i-1,k,0]+a[k]-a[i-1],time[k]),Max(f[i,k+1,1]+a[k+1]-a[k],time[k]));
							end;
			end;
	ans:=Maxlongint;
	for i:=1 to n do
		begin
			if f[i,i,0]+abs(a[i]-b)<ans then ans:=f[i,i,0]+abs(a[i]-b);
			if f[i,i,1]+abs(a[i]-b)<ans then ans:=f[i,i,1]+abs(a[i]-b);
		end;
	writeln(ans);
END.


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值