2018 4.21 Noip2015 day1 考试总结

妈妈我再也不要斗地主了

心态蹦了啊最后一道题改了两个多小时都没改全对

好了回归正题来一波今天考试总结加题解

T1 神奇幻方

其实就是一道很简单的模拟题,根据题目所给的信息来模拟就可以了,可以记录一个前驱这样可以很快的判断

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int maxn=45;

int mat[maxn][maxn];

int n,prex,prey;

int main()
{
	freopen("magic.in","r",stdin);
	freopen("magic.out","w",stdout);
	scanf("%d",&n);
	int mid=(1+n)>>1;
	mat[1][mid]=1;
	prex=1;
	prey=mid;
	for (int i=2;i<=n*n;i++)
	{
		if (prex==1&&prey!=n)
		{
			mat[n][prey+1]=i;
			prex=n;
			prey=prey+1;
			continue;
		}
		if (prey==n&&prex!=1)
		{
			mat[prex-1][1]=i;
			prex=prex-1;
			prey=1;
			continue;
		}
		if (prex==1&&prey==n)
		{
			mat[prex+1][prey]=i;
			prex=prex+1;
		}
		if (prex!=1&&prey!=n)
		{
			if (mat[prex-1][prey+1]==0)
			{
				mat[prex-1][prey+1]=i;
				prex=prex-1;
				prey=prey+1;
			}
			else
			{
				mat[prex+1][prey]=i;
				prex=prex+1;
			}   
		}
	}
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=n;j++)
		   printf("%d ",mat[i][j]);
		printf("\n");
	}
	return 0;
}

T2 信息传递

呃呃呃据说旁边的大佬用并查集做出来了啊啊

但是这道题其实很简单啊,每个人只能连出一条边,所以最多形成一个环,直接Tarjan求个最小环就可以了

#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;

const int maxn=200005;

int dfn[maxn],color[maxn],low[maxn],colorv[maxn];

int head[maxn],nxt[maxn],tov[maxn],stk[maxn*2];

bool vis[maxn];

int n,tot=0,top=0,cnt=0,idx=0,ans=1e9;

void add(int u,int v)
{
	tot++;
	tov[tot]=v;
	nxt[tot]=head[u];
	head[u]=tot;
}

void tarjan(int u)
{
	idx++;
	low[u]=dfn[u]=idx;
	stk[++top]=u;
	vis[u]=1;
	for (int i=head[u];i;i=nxt[i])
	{
		int v=tov[i];
		if (!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if (vis[v])
		{
			low[u]=min(dfn[v],low[u]);
		}
	}
	if (dfn[u]==low[u])
	{
		cnt++;
		while (1)
		{
			int p=stk[top];
			top--;
			vis[p]=0;
			color[p]=cnt;
			colorv[cnt]++;
			if (p==u)
			   break;
		}
	}
}

int main()
{
	freopen("message.in","r",stdin);
	freopen("message.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		int to;
		scanf("%d",&to);
		add(i,to);
	}
	for (int i=1;i<=n;i++)
	   if (!dfn[i])
	      tarjan(i);
	for (int i=1;i<=n;i++)
	{
		if (colorv[color[i]]>=2&&colorv[color[i]]<ans)
		   ans=colorv[color[i]];
	}
	printf("%d\n",ans);
	return 0;
}

message拼错了强行摔锅给李尬书

T3不解释了真的考验代码能力

按照题目顺序模拟单顺,双顺,三顺,三带一二,四带二的情况,根最优情况可以剪枝

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

int T,n,x,y,ans;
int a[20];

void clear()
{
	memset(a,0,sizeof(a));
	ans=0;
}
bool check()
{
	for (int i=1;i<=15;++i)
		if (a[i]) return false;
	return true;
}
void dfs(int dep)
{
	if (dep>ans) return;
	if (check())
	{
		ans=min(ans,dep);
		return;
	}
	int sum=0;
	for (int i=1;i<=13;++i)
		if (a[i]) sum++;
	if (a[14]+a[15]) sum++;
	ans=min(ans,dep+sum);
	for (int kind=1;kind<=5;++kind)
	{
		
		if (kind==1)
		{
			for (int i=1;i<=8;++i)
				if (a[i])
				{
					bool flag=true;
					for (int j=i+1;j<=i+3;++j)
						if (!a[j]) {flag=false;break;}
					if (!flag) continue;
					
					for (int j=i+4;j<13&&a[j];++j)
					{
						for (int k=i;k<=j;++k) --a[k];
						dfs(dep+1);
						for (int k=i;k<=j;++k) ++a[k];
					}
				}
		}
		if (kind==2)
		{
			for (int i=1;i<=10;++i)
				if (a[i]>=2&&a[i+1]>=2)
					for (int j=i+2;j<13&&a[j]>=2;++j)
					{
						for (int k=i;k<=j;++k) a[k]-=2;
						dfs(dep+1);
						for (int k=i;k<=j;++k) a[k]+=2;
					}
		}
		if (kind==3)
		{
			for (int i=1;i<=11;++i)
				if (a[i]>=3)
				{
					if (a[i+1]<3) continue;
					
					for (int j=i;j<13&&a[j]>=3;++j)
					{
						for (int k=i;k<=j;++k) a[k]-=3;
						dfs(dep+1);
						for (int k=i;k<=j;++k) a[k]+=3;
					}
				}
		}
		
		if (kind==4)
		{
			for (int i=1;i<=13;++i)
				if (a[i]>=3)
				{
					a[i]-=3;
					for (int j=1;j<=15;++j)
						if (a[j])
						{
							--a[j];
							dfs(dep+1);
							++a[j];
						}
					
					for (int j=1;j<=15;++j)
						if (a[j]>=2)
						{
							a[j]-=2;
							dfs(dep+1);
							a[j]+=2;
						}
					a[i]+=3;
				}
			
		}
		if (kind==5)
		{
			
			for (int i=1;i<=15;++i)
				if (a[i]>=4)
				{
					a[i]-=4;
					for (int j=1;j<=15;++j)
						if (a[j])
						{
							--a[j];
							for (int k=j;k<=15;++k)
								if (a[k])
								{
									--a[k];
									dfs(dep+1);
									++a[k];
								}
							++a[j];
						}
					a[i]+=4;
				}
			for (int i=1;i<=15;++i)
				if (a[i]>=4)
				{
					a[i]-=4;
					for (int j=1;j<=15;++j)
						if (a[j]>=2)
						{
							a[j]-=2;
							for (int k=j;k<=15;++k)
								if (a[k]>=2)
								{
									a[k]-=2;
									dfs(dep+1);
									a[k]+=2;
								}
							a[j]+=2;
						}
					a[i]+=4;
				}
		}
	}
}
int main()
{
	freopen("landlords.in","r",stdin);
	freopen("landlords.out","w",stdout);
	scanf("%d%d",&T,&n);
	while (T--)
	{
		clear();
		for (int i=1;i<=n;++i)
		{
			scanf("%d%d",&x,&y);
			if (!x) a[y+13]++;
			if (x==1||x==2) a[x+11]++;
			if (x>=3) a[x-2]++;
		}
		for (int i=1;i<=13;++i)
			if (a[i]) ans++;
		if (a[14]+a[15]) ans++;
		dfs(0);
		printf("%d\n",ans);
	}
}

今天的考试总体来说不难T1,T2基本送分,T3考验一波代码能力,然后就是一波面向数据的编程

问题还是不大,继续搞图论刷题去了

猜你喜欢

转载自blog.csdn.net/beloved_rancy/article/details/80030708