noip2015day1题解

晚上只睡了三个小时的情况下做的这套题(考试的时候做一会儿睡一会儿),觉得题很简单,半小时敲完一二题,结果第三道题的深搜一直没有搜出来qwq。。。。最后还是写了30分的暴力算法。。。。心态巨崩无比(本来以为自己可以AK的)

T1神奇的幻方

我相信只要会写程序的人都会做这道题(话说近几年的大模拟的题真的不少啊)

#include<cstdio>
const int MAXN=45;
int f[MAXN][MAXN];
int main()
{
	//freopen("magic.in","r",stdin);
	//freopen("magic.out","w",stdout);
	int n;
	std::scanf("%d",&n);
	int mid=(1+n)>>1;
	f[1][mid]=1;
	for(int i=2;i<=n*n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int k=1;k<=n;k++)
			{
				if(f[j][k]==i-1)
				{
					if(j==1&&k!=n)
					{
						f[n][k+1]=i;
					}
					if(k==n&&j!=1)
					{
						f[j-1][1]=i;
					}
					if(j==1&&k==n)
					{
						f[j+1][k]=i;
					}
					if(j!=1&&k!=n)
					{
						if(f[j-1][k+1]==0)
						{
							f[j-1][k+1]=i;
						}
						else 
						{
							f[j+1][k]=i;
						}
					}
				}
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			printf("%d ",f[i][j]);
		}
		printf("\n");
	}
	return 0;
}

T2 信息传递

画一下图就能知道这道题的目的就是让求一个DAG里面的最小环,由于题目保证有解,所以直接tarjan缩点虐之(值得一提的是这道题出题人貌似没有卡数据,如果在递归的时候所有点全部进栈的话应该是会卡爆的),当然,并查集或者直接线性扫描都能过这题,当做水题刷就好了

#include<cstdio>
#include<algorithm>
const int MAXN=2e5+5;
struct Edge
{
	int nxt;
	int to;
}edge[MAXN<<1];
int num;
int head[MAXN];
void add(int from,int to)
{
	edge[++num].nxt=head[from];
	edge[num].to=to;
	head[from]=num;
}
int indx;
int color[MAXN];
int dgr[MAXN];
int dfn[MAXN];
int low[MAXN];
int stk[MAXN];
bool vis[MAXN];
int top;
int cnt;
void tarjan(int x)
{
	indx++;
	dfn[x]=low[x]=indx;
	stk[++top]=x;
	vis[x]=1;
	for(int i=head[x];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(!dfn[v])
		{
			tarjan(v);
			low[x]=std::min(low[x],low[v]);
		}
		else
		if(vis[v])
		{
			low[x]=std::min(low[x],dfn[v]);
		}
	}
	if(dfn[x]==low[x])
	{
		cnt++;
		while(1)
		{
			int u=stk[top--];
			vis[u]=0;
			dgr[cnt]++;
			color[u]=cnt;
			if(u==x)
			{
				break;
			}
		}
	}
}
int main()
{
	//freopen("message.in","r",stdin);
	//freopen("message.out","w",stdout);
	int n;
	std::scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int ti;
		std::scanf("%d",&ti);
		add(i,ti);
	}
	for(int i=1;i<=n;i++)
	{
		if(!dfn[i])
		{
			tarjan(i);
		}
	}
	int ans=0x7fffffff;
	for(int i=1;i<=cnt;i++)
	{
		if(dgr[i]!=1&&dgr[i]<ans)
		{
			ans=dgr[i];
		}
	}
	printf("%d\n",ans);
	return 0;
}

T3 斗地主

究极大模拟。。。。据说剪枝以后的状压+dfs能过95分,不过正解是贪心+dfs暴搜,由于内存和时间都不算紧张,所以说最后的答案就完全靠细不细心了(然而样例2的答案一直少了1,最后发现就是单纯的没有加而已。。。)

#include<cstdio>
#include<cstring>
#include<algorithm>
int T,n;
int cnt[16];
int ans=23;
void dfs(int x)
{
	if(x>ans)
	{
		return;
	}
	int s1;
	int s2;
	int s3;
	int s4;
	s1=s2=s3=s4=0;
	for(int i=1;i<=14;i++)
	{
		if(cnt[i]==2)
		{
			s2++;
		}
		if(cnt[i]==1)
		{
			s1++;
		}
	}
	for(int i=1;i<=14;i++)
	{
		if(cnt[i]==4)
		{
			s4++;
			if(s1>=2)
			{
				s1-=2;
			}
			else if(s2>=2)
			{
				s2-=2;
			}
			else if(s2>=1)
			{
				s2--;
			}
		}
	}
	for(int i=1;i<=14;i++)
	{
		if(cnt[i]==3)
		{
			s3++;
			if(s1>=1)
			{
				s1--;
			}
			else if(s2>=1)
			{
				s2--;
			}
		}
	}
	ans=std::min(ans,x+s1+s2+s3+s4);
	int j;
	for(int i=1;i<=8;i++)
	{
		for(j=i;j<=12;j++)
		{
			cnt[j]--;
			if(cnt[j]<0)
			{
				break;
			}
			if(j-i>=4)
			{
				dfs(x+1);
			}
		}
		if(j==13)
		{
			j--;
		}
		while(j>=i)cnt[j--]++;
	}
	for(int i=1;i<=10;i++)
	{
		for(j=i;j<=12;j++)
		{
			cnt[j]-=2;
			if(cnt[j]<0) break;
			if(j-i>=2)
			{
				dfs(x+1);
			}
		}
		if(j==13)
		{
			j--;
		}
		while(j>=i) cnt[j--]+=2;
	}
	for(int i=1;i<=11;i++)
	{
		for(j=i;j<=12;j++)
		{
			cnt[j]-=3;
			if(cnt[j]<0)
			{
				break;
			}
			if(j-i>=1)
			{
				dfs(x+1);
			}
		}
		if(j==13)
		{
			j--;
		}
		while(j>=i)
		{
			cnt[j--]+=3;
		}
	}
}
int main()
{
	//freopen("landlords.in","r",stdin);
	//freopen("landlords.out","w",stdout);
	int T,n;
	std::scanf("%d%d",&T,&n);
	while(T--)
	{
		std::memset(cnt,0,sizeof(cnt));
		ans=23;
		for(int i=1;i<=n;i++)
        {
	        int x,y;
	        std::scanf("%d%d",&x,&y);
	        if(x==0)
	        {
		        cnt[14]++;
	        }
	        else 
	        if(x==1)
	        {
		        cnt[12]++;
	        }
	        else 
		    if(x==2)
	        {
		        cnt[13]++;
	        }
	        if(x>=3)
	        {
		        cnt[x-2]++;
	        }
        }
		dfs(0);
		printf("%d\n",ans);
	}
	return 0;
}
/*
1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1

1 17
12 3
4 3
2 3
5 4
10 2
3 3
12 2
0 1
1 3
10 1
6 2
12 1
11 3
5 2
12 4
2 2
7 2
*/

猜你喜欢

转载自blog.csdn.net/Amuseir/article/details/80029169
今日推荐