POJ 3269 USACO FEB GOLD newbarn

题目大意 给N(1<n<=1w)个牛的坐标xi,yi(0<=|xi,yi|<=1w 求其他点到没有牛的点的最短曼哈顿距离和以及这些点有多少个.

我语文不好= - =连接:http://poj.org/problem?id=3270

我果然还是若菜呢。很难过吧,自己还是半吊子水平,这种题目都想不出来!

首先,因为是曼哈顿距离,所以X,Y轴可以分开来算,

然后,这道题稍微算一下就能发现,对于x y轴 从该行/列到其他的点的x距离(或y距离)是一个单谷函数...反正就是类似于二次函数的那种图像啦(>﹏<)

所以很明显 解就在x y的最低处所形成的矩形当中,只要从中剔除出有奶牛的地方就好了~~~

还有!!!有可能会有最后得到的矩形只包含一个点并且那个点有奶牛的情况!这个时候只要判断一下这个点的周围是否是最优解(因为奶牛必定不相临)就行啦~!~

拉拉拉拉拉= - =。。NOIP幸运A+++++考了450= - =。。。。就这样一路RP++++下去吧!@!~!~!

code:

var
  xl,yl,xr,yr,n,sum,tmp,min,count,i,j,k:longint;
  flag:boolean;
  x,y,xx,yy:array[-10001..10001] of longint;
  a,b:array[0..10005] of longint;
begin
  read(n);
  fillchar(x,sizeof(x),0);
  fillchar(y,sizeof(y),0);
  for i:=1 to n do
    begin
	  read(a[i],b[i]);
	  x[a[i]]:=x[a[i]]+1;
	  y[b[i]]:=y[b[i]]+1;
	end;
  fillchar(xx,sizeof(xx),0);
  fillchar(yy,sizeof(yy),0);

  sum:=0;tmp:=0;
  for i:=-10000 to 10000 do
    begin
	  tmp:=tmp+sum;
	  xx[i]:=xx[i]+tmp;
	  sum:=sum+x[i];
	end;	
  sum:=0;tmp:=0;
  for i:= 10000 downto -10000 do
    begin
	  tmp:=tmp+sum;
	  xx[i]:=xx[i]+tmp;
	  sum:=sum+x[i];
	end;

  sum:=0;tmp:=0;
  for i:=-10000 to 10000 do
    begin
	  tmp:=tmp+sum;
	  yy[i]:=yy[i]+tmp;	  	 
	  sum:=sum+y[i];
	end;	
  sum:=0;tmp:=0;
  for i:= 10000 downto -10000 do
    begin
	  tmp:=tmp+sum;
	  yy[i]:=yy[i]+tmp;	  
	  sum:=sum+y[i];
	end;
	
  min:=maxlongint;xr:=10000;yr:=10000;
  for i:=-10000 to 10000 do
    begin 
	  if xx[i]<min then
	    begin
		  xl:=i;
		  min:=xx[i];
		end;
	  if xx[i]>min then
	    begin
		  xr:=i-1;
		  break;
		end;
	end;  
  min:=maxlongint;
  for i:=-10000 to 10000 do
    begin 
	  if yy[i]<min then
	    begin
		  yl:=i;
		  min:=yy[i];
		end;
	  if yy[i]>min then
	    begin
		  yr:=i-1;
		  break;
		end;
	end;
  count:=0;
  for i:=xl to xr do
    for j:=yl to yr do
	  begin
	    flag:=true;
		if (x[i]>0) and (y[j]>0) then
		  for k:=1 to n do
		    if (a[k]=i) and (b[k]=j) then
		      begin
			    flag:=false;
			    break;
			  end;
		if flag then count:=count+1;
	  end;
  if count>0 then
    begin
	  writeln(xx[xl]+yy[yl],' ',count);
	  halt;
	end;
  min:=maxlongint;
  for i:=xl-10 to xr+10 do
    for j:=yl-10 to yr+10 do
	  if (i=xl) and (j=yl) then continue else
	    begin
		  flag:=false;
		  for k:=1 to n do
		    if (a[k]=i) and (b[k]=j) then 
			  begin
			    flag:=true;
				break;
			  end;
		  if flag then continue;
		  if (xx[i]+yy[j])<min then
		    begin
			  min:=xx[i]+yy[j];
			  count:=0;
			end;
		  if (xx[i]+yy[j])=min then count:=count+1;
		end;
  writeln(min,' ',count);
end.

代码略长呢!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值