2005 ACM-ICPC世界总决赛试题分析1-3

1

#include<stdio.h>
#include<math.h>
struct line
{
	double x1,y1,x2,y2;
};
struct point
{
	double x,y;
};
const double delta=1e-6;
bool ok;
int T,n,m,i,j,k;
double scale;
point pL,pS;
line tL;
line L[60],S[60],SN[60];
line in()
{
	double tmp;
	line t;
	scanf("%lf %lf %lf %lf",&t.x1,&t.y1,&t.x2,&t.y2);
	if(t.x1>t.x2+delta)
	{
		tmp=t.x1;
		t.x1=t.x2;
		t.x2=tmp;
	}
	if(t.y1>t.y2+delta)
	{
		tmp=t.y1;
		t.y1=t.y2;
		t.y2=tmp;
	}
	return t;
}

bool same(double x,double y)
{
	return (y-delta<x && x<y+delta);
}

bool findS(line p)
{
	int i;
	for(i=0;i<n;i++)
	{
		if(same(p.x1,p.x2)&&same(L[i].x1,L[i].x2)&&same(p.x1,L[i].x1))
			if(L[i].y1<=p.y1&&p.y2<=L[i].y2)
				return true;
		if(same(p.y1,p.y2)&&same(L[i].y1,L[i].y2)&&same(p.y1,L[i].y1))
			if(L[i].x1<=p.x1&&p.x2<=L[i].x2)
				return true;
	}
	return false;
}

bool findL(line p)
{
	int i;
	for(i=0;i<m;i++)
	{
		if(same(p.x1,p.x2)&&same(SN[i].x1,SN[i].x2)&&same(p.x1,SN[i].x1))
			if(SN[i].y1<=p.y1 && p.y2<=SN[i].y2)
				return true;
		if(same(p.y1,p.y2)&&same(SN[i].y1,SN[i].y2)&&same(p.y1,SN[i].y1))
			if(SN[i].x1<=p.x1&&p.x2<=SN[i].x2)
				return true;
	}
	return false;
}

double dis(double x,double y)
{
	return sqrt(x*x+y*y);
}

bool check()
{
	double MaxX,MaxY,MinX,MinY;
	int i,j,k;
	MaxX=MinX=pL.x;
	MaxY=MinY=pL.y;
	for(i=0;i<m;i++)
	{
		SN[i].x1=(S[i].x1-pS.x)*scale + pL.x;
		SN[i].y1=(S[i].y1-pS.y)*scale + pL.y;
		SN[i].x2=(S[i].x2-pS.x)*scale + pL.x;
		SN[i].y2=(S[i].y2-pS.y)*scale + pL.y;
		if(!findS(SN[i]))
			return false;
		if(SN[i].x1<MinX)
			MinX=SN[i].x1;
		if(SN[i].x2>MaxX)
			MaxX=SN[i].x2;
		if(SN[i].y1<MinY)
			MinY=SN[i].y1;
		if(SN[i].y2>MaxY)
			MaxY=SN[i].y2;
	}
	for(i=0;i<n;i++)
	{
		if(same(L[i].x1,L[i].x2))
		{
			if(L[i].x1>MaxX)
			{
				if(L[i].y1>MaxY)
				{
					if(dis(L[i].x1-MaxX,L[i].y1-MaxY)<0.005)
						return false;
				}
				else if( L[i].y2<MinY)
				{
					if(dis(L[i].x1-MaxX,L[i].y2-MinY)<0.005)
						return false;
				}
				else if(L[i].x1-MaxX<0.005)
					return false;
			}
			else if(L[i].x2<MinX)
			{
				if(L[i].y1>MaxY)
				{
					if(dis(L[i].x2-MinX,L[i].y1-MaxY)<0.005)
						return false;
				}
				else if(L[i].y2<MinY)
				{
					if(dis(L[i].x2-MinX,L[i].y2-MinY)<0.005)
						return false;
				}
				else if(MinX-L[i].x2<0.005)
					return false;
			}
			else
			{
				if(L[i].y2<MinY-0.005 || L[i].y1>MaxY + 0.005)
					continue;
				if(L[i].y2<MinY || L[i].y1>MaxY)
					return false;
				tL=L[i];
				if(tL.y1<MinY)
					tL.y1=MinY;
				if(tL.y2>MaxY)
					tL.y2=MaxY;
				if(!findL(tL))
					return false;
			}
		}
		else
		{
			if(L[i].y1>MaxY)
			{
				if(L[i].x1>MaxX)
				{
					if(dis(L[i].x1-MaxX,L[i].y1-MaxY)<0.005)
						return false;
				}
				else if(L[i].x2<MinX)
				{
					if(dis(L[i].x2-MinX,L[i].y1-MaxY)<0.005)
						return false;
				}
				else if(L[i].y1-MaxY<0.005)
					return false;
			}
			else if(L[i].y2<MinY)
			{
				if(L[i].x1>MaxX)
				{
					if(dis(L[i].x1-MaxX,L[i].y2-MinY)<0.005)
						return false;
				}
				else if(L[i].x2<MinX)
				{
					if(dis(L[i].x2-MinX,L[i].y2-MinY)<0.005)
						return false;
				}
				else if(MinY-L[i].y2<0.005)
					return false;
			}
			else
			{
				if(L[i].x2<MinX-0.005||L[i].x1>MaxX+0.005)
					continue;
				if(L[i].x2<MinX || L[i].x1>MaxX)
					return false;
				tL=L[i];
				if(tL.x1<MinX)
					tL.x1=MinX;
				if(tL.x2<MaxX)
					tL.x2=MaxX;
				if(!findL(tL))
					return false;
			}
		}
	}
	return true;
}

void work()
{
	int k;
	if(m==1)
	{
		scale=0.005/(S[0].x2-S[0].x1+S[0].y2-S[0].y1);
		ok=scale<=1 && check();
	}
	else for(k=0;k<n;k++)
		if((L[k].x1-L[k].x2)*(S[1].x1-S[1].x2) || (L[k].y1-L[k].y2)*(S[1].y1-S[1].y2))
		{
			if(S[1].x1!=S[1].x2)
			{
				if(same(S[1].y1,pS.y))
				{
					if(!same(S[1].x1,pS.x))
						scale=(L[k].x1-pL.x)/(S[1].x1-pS.x);
					else
						scale=(pL.x-L[k].x2)/(pS.x-S[1].x2);
				}
				else 
					scale=(L[k].y1-pL.y)/(S[1].y1-pS.y);
			}
			else
			{
				if(same(S[1].x1,pS.x))
				{
					if(!same(S[1].y1,pS.y))
						scale=(L[k].y1-pL.y)/(S[1].y1-pS.y);
					else
						scale=(pL.y-L[k].y2)/(pS.y-S[1].y2);
				}
				else
					scale=(L[k].x1-pL.x)/(S[1].x1-pS.x);
			}
			ok=scale<=1&&scale>delta&&check();
			if(ok)
				return ;
			
	}
}

int main()
{
	T=0;
	while(scanf("%d %d",&m,&n) && (m||n))
	{
		for(i=0;i<m;i++)
			S[i]=in();
		for(i=0;i<n;i++)
			L[i]=in();
		ok=false;
		for(i=0;i<n;i++)
			for(j=0;j<m;j++) if(!ok)
			{
				tL=S[0];
				S[0]=S[j];
				S[j]=tL;
				pL.x=L[i].x1;
				pL.y=L[i].y1;
				pS.x=S[0].x1;
				pS.y=S[0].y1;
				work();
				if(ok)
					break;
				pL.x=L[i].x2;
				pL.y=L[i].y2;
				pS.x=S[0].x2;
				pS.y=S[0].y2;
				work();
				if(ok)
					break;
			}
			if(ok)
				printf("Case %d: valid puzzle\n\n",++T);
			else
				printf("Case %d: impossible\n\n",++T);
	}
	return 0;
}

2

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
struct coor
{
	double x,y;
};
const int MaxB=50;
const int MaxC=50;
const int MaxS=50*50;

int B,C,R,Q,i,j,k,cases;
coor BTS[MaxB],city[MaxC];
int S[MaxC][MaxC];
double dis(double x1,double y1,double x2,double y2)
{
	return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}
int area(double x,double y)
{
	int i,k;
	k=0;
	double min,tmp;
	min=dis(x,y,BTS[0].x,BTS[0].y);
	for(i=1;i<B;i++)
	{
		tmp=dis(x,y,BTS[i].x,BTS[i].y);
		if(tmp<min)
		{
			min=tmp;
			k=i;
		}
	}
	return k;
}

int get_switch(double x1,double y1,double x2,double y2)
{
	if(area(x1,y1)==area(x2,y2))
		return 0;
	if(dis(x1,y1,x2,y2)<1e-6)
		return 1;
	return get_switch(x1,y1,(x1+x2)/2,(y1+y2)/2)+get_switch((x1+x2)/2,(y1+y2)/2,x2,y2);
}

bool init()
{
	scanf("%d %d %d %d",&B,&C,&R,&Q);
	if(B==0&&C==0&&R==0&&Q==0)
		return false;
	for(i=0;i<B;i++)
		scanf("%lf %lf",&BTS[i].x,&BTS[i].y);
	for(i=0;i<C;i++)
		scanf("%lf %lf",&city[i].x,&city[i].y);
	memset(S,0,sizeof(S));
	for(i=0;i<R;i++)
	{
		scanf("%d %d",&j,&k);
		j--;k--;
		S[j][k]=S[k][j]=1;
	}
	for(i=0;i<C;i++)
		for(j=i+1;j<C;j++)
		{
			if(S[i][j]==0)
				S[i][j]=MaxS;
			else
				S[i][j]=get_switch(city[i].x,city[i].y,city[j].x,city[j].y);
			S[j][i]=S[i][j];
		}
	for(i=0;i<C;i++)
		S[i][i]=0;
	return true;
}

int main()
{
	cases=0;
	while(init())
	{
		printf("Case %d:\n",++cases);
		for(k=0;k<C;k++)
			for(i=0;i<C;i++)
				for(j=0;j<C;j++)
					if(S[i][j]>S[i][k]+S[k][j])
						S[i][j]=S[i][k]+S[k][j];
		for(i=0;i<Q;i++)
		{
			scanf("%d %d",&j,&k);
			j--;k--;
			if(S[j][k]>=MaxS)
				printf("Impossible\n");
			else
				printf("%d\n",S[j][k]);
		}
	}
	return 0;
}

3

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int MaxC=20;
const int MaxJ=10;
int cases,NC,NJ,T,DC,map,best_map,ans,i,k;
int road[MaxC][MaxC],judges[MaxJ],fa[MaxC];
bool init()
{
	int NR,i,C1,C2;
	scanf("%d",&NC);
	if(NC==-1)
		return false;
	scanf("%d",&DC);
	DC--;
	T=1<<DC;
	scanf("%d",&NR);
	memset(road,0,sizeof(road));
	ans=1000;
	for(i=0;i<NR;i++)
	{
		scanf("%d %d",&C1,&C2);
		C1--;C2--;
		scanf("%d",&road[C1][C2]);
		road[C2][C1]=road[C1][C2];
		ans+=road[C1][C2];
	}
	scanf("%d",&NJ);
	for(i=0;i<NJ;i++)
	{
		scanf("%d",&judges[i]);
		judges[i]--;
		T+=1<<judges[i];
	}
	return true;
}

void check(int map)
{
	int i,j,k,sum,min;
	int d[MaxC];
	for(i=0;i<MaxC;i++)
		d[i]=-2;
	d[DC]=-1;
	for(i=0;i<MaxC;i++)
		if(((1<<i)&map)&&road[DC][i])
		{
			d[i]=road[DC][i];
			fa[i]=DC;
		}
	sum=0;
	while(1)
	{
		min=ans+10;
		for(i=0;i<MaxC;i++)
			if(d[i]>0&&d[i]<min)
			{
				min=d[i];
				k=i;
			}
		if(min>ans)
			break;
		sum+=min;
		d[k]=-1;
		for(i=0;i<MaxC;i++)
			if((1<<i)&map&&road[k][i])
				if(d[i]==-2||d[i]>road[k][i])
				{
					d[i]=road[k][i];
					fa[i]=k;
				}
	}
	for(i=0;i<MaxC;i++)
		if(((1<<i)&map)&&d[i]==-2)
			return;
	if(sum<ans)
	{
		ans=sum;
		best_map=map;
	}
	else if(sum==ans)
	{
		j=0;k=0;
		for(i=0;i<MaxC;i++)
		{
			if((1<<i)&best_map) j++;
			if((1<<i)&map) k++;
		}
		if(j>k)
		{
			best_map=map;
			return;
		}
		if(j<k)
			return;
		for(i=0;i<MaxC;i++)
		{
			if(((1<<i)&best_map)&&!((1<<i)&map))
				return;
			if(!((1<<i)&best_map)&&((1<<i)&map))
			{
				best_map=map;
				return;
			}
		}
	}
}

int main()
{
	cases=0;
	while(init())
	{
		best_map=0;
		for(map=0;map<(1<<NC);map++)
			if((map&T)==T)
				check(map);
		printf("Case %d: distance = %d\n",++cases,ans);
		check(best_map);
		for(i=0;i<NJ;i++)
		{
			printf("   %d",judges[i]+1);
			k=judges[i];
			while(k!=DC)
			{
				printf("-%d",fa[k]+1);
				k=fa[k];
			}
			printf("\n");
		}
		printf("\n");
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值