2019.06.09【NOIP普及组】模拟赛C组

2019.06.09【NOIP普及组】模拟赛C组

超链接为pdf题面,请先登录。

泽泽在中国

渣题
用S来表示长城的长度,t来表示目前的所用的时间。
不断地读入a,b,t,而t不断地加 (b-a+1)t,表示这一段所用的时间。最后S不断减掉 bi-ai+1,则就是剩下的长度了。最后t还要加上加上s1,计算普通的长城的时间。
BAS code:

#include
int s,n,x,y,z,t,i;
int main()
{
	freopen("china.in","r",stdin);
	freopen("china.out","w",stdout);
	scanf("%d%d",&s,&n);
	for(i=1;i<=n;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		t+=(y-x+1)*z;
		s-=(y-x+1);
	}
	printf("%d\n",t+s);
}

泽泽在英国

对于此题,暴力枚举:
用f[I,j]表示第i座建筑高度为j时的最大面积。则i-1 基本思路是这样的:

ZOJ code:

#include
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int a[1000010];
int main()
{
	freopen("england.in","r",stdin);
	freopen("england.out","w",stdout);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	int mx=-1;
	for(int i=1;i<=n;i++)
		mx=max(a[i],mx);
	int s=0;
	int ans=-1;
	for(int i=1;i<=mx;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[j]>=i)
			{
				s+=i;
				continue;
			}
			if(a[j]<i)
			{
				ans=max(ans,s);
				s=0;
				continue;
			}
		}
		ans=max(ans,s);
		s=0;
	}
	printf("%d",ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

泽泽在巴西

这道理,正解为搜索,可以用最短路做。
首先,先教大家两个判断公式:

(1).判断三点共线:

如果Q,P1,P2满足:(Qx-P1x)(P2y-P2y)=(P2x-P1x)(Qy-P1y)
则Q,P1,P2在同一条直线上

(2).判断三点中一点在另两点形成的线段之间:

如果满足(1),且min(P1x,P2x) <= Qx,Qx<=max(P1x,P2x)
且min(P1y,P2y)<=Qy,Qy<=max(P1y,P2y))
则Q在P1,P2所形成的线段之间

然后理解理解:

一开始,球权在泽择手中,他可以选择自己射门,也可以选择传给其他球员射门,选择时间略短的一种方案(先保证没有流氓拦截)
而被传球的球员也可以选择自己射门,也可以选择传给其他球员射门
则:
⑴举每个泽泽队伍的队员B,看看是A直接射门优还是A传球给B射门优
⑵举每个泽泽队伍的队员C,看看是B直接射门优还是B传球给C射门优

DFS code:

#include
#include
#include
#define r register int
using namespace std;
int n,m,x[301],y[301],a,b,bz[5001][5001],l[301];
double map[302][302],ans;
void dfs(int k,double t)
{
	if (!ans||ans>t+map[301][k])
	ans=t+map[301][k];
	for (r i=1;i<=n;++i)
	if (i-k)
	if (map[i][k]+1)
	if (!l[i]||l[i]>t+map[i][k])
	{
		l[i]=t+map[i][k];
		dfs(i,t+map[i][k]);
	}
}
int main()
{
	freopen("brazil.in","r",stdin);
	freopen("brazil.out","w",stdout);
	scanf("%d%d%d%d",&a,&b,&n,&m);
	for (r i=1;i<=n;++i)
	scanf("%d%d",&x[i],&y[i]);
	for (r i=1;i<=m;++i)
	{
		int x2,y2;
		scanf("%d%d",&x2,&y2);
		bz[x2+2500][y2+2500]=1;
	}
	for (r i=1;i<=n;++i)
	for (r j=i+1;j<=n;++j)
	{
		bool bz2=1;
		int p=x[i]-x[j],q=y[i]-y[j];
		int o=__gcd(p,q),nowx=x[j],nowy=y[j];
		if (o<0)
		o=-o;
		p/=o,q/=o;
		for (r k=1;k<o;++k)
		{
			nowx+=p;nowy+=q;
			if (bz[nowx+2500][nowy+2500])
			{
				bz2=0;
				break;
			}
		}
		if (bz2)
		map[i][j]=map[j][i]=sqrt(double((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])));
		else
		map[i][j]=map[j][i]=-1;
	}
	for (r i=1;i<=n;++i)
	map[i][301]=map[301][i]=sqrt(double((x[i]-a)*(x[i]-a)+(y[i]-b)*(y[i]-b)))*2;
	ans=map[1][301];
	dfs(1,0);
	printf("%d",int(ans+0.5));
	fclose(stdin);
	fclose(stdout);
	return 0;
}

而最短路代码,首先构造路线,然后进行搜索最优:
SPFA code:

#include 
#include 
#include 
#define INF 2147483647.0
#define ER 0.00000001
using namespace std;
queue<int> q;
struct P
{
	int x,y;
}a[3100],b[1100],d;
struct Edge
{
	int to,next;double val;
}edge[450100];
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
int n,m,ans,len,head[3100];
bool inq[3100];
double dis[3100];
inline double gd(int x1,int y1,int x2,int y2)
{
	return sqrt((double)((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
}
inline bool eq(double a,double b)
{
	return fabs(a-b)<=ER;
}
inline bool br(double a,double b)
{
	return (a-b)>ER;
}
bool line(P a,P b,P c)
{
	if(fabs(gd(a.x,a.y,b.x,b.y)-gd(a.x,a.y,c.x,c.y)-gd(c.x,c.y,b.x,b.y))<0.00001)
		return false;
	return true;
}
void add_edge(int u,int v,double f)
{
	edge[++len]=(Edge){v,head[u],f};
	head[u]=len;
}
void spfa()
{
	for(int i=2;i<=n;++i)
		dis[i]=INF;
	inq[1]=1;q.push(1);
	int u,v;
	while(!q.empty())
	{
		u=q.front();
		q.pop();
		inq[u]=0;
		for(int i=head[u];i;i=edge[i].next)
		{
			v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].val)
				dis[v]=edge[i].val+dis[u];
				if(!inq[v])
				{
					q.push(v);
					inq[v]=1;
				}
		}
	}
}
int main()
{
	freopen("brazil.in","r",stdin);
	freopen("brazil.out","w",stdout);
	scanf("%d %d %d %d",&d.x,&d.y,&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%d %d",&a[i].x,&a[i].y);
	for(int i=1;i<=m;++i)
		scanf("%d %d",&b[i].x,&b[i].y);
	for(int i=1;i<=n;++i)
		for(int j=i+1;j<=n;++j)
		{
			bool bz=0;
			for(int k=1;k<=m;++k)
				if(!line(a[i],a[j],b[k]))
				{
					bz=1;break;
				}
			if(!bz)
			{
				add_edge(i,j,gd(a[i].x,a[i].y,a[j].x,a[j].y));
				add_edge(j,i,gd(a[i].x,a[i].y,a[j].x,a[j].y));
			}
		}
	for(int i=1;i<=n;++i)
		add_edge(i,n+1,gd(a[i].x,a[i].y,d.x,d.y)*2);
	++n;
	spfa();
	if((int)dis[n]*1.0+0.5>=dis[n])
		ans=(int)dis[n];
	else
		ans=(int)dis[n]+1;
	printf("%d",(int)ans);
	return 0;
}

你可能感兴趣的:(比赛题解)