TEST2018.4.21(Noip2015提高组Day1)

TEST2018.4.21(Noip2015提高组Day1)

为2019级lizw0520zzh的学生献上福利!!!

题目描述(感谢洛谷爸爸):  神奇的幻方    信息传递    斗地主


T1 神奇的幻方:

模拟题,很简单,按照题目描述进行模拟就行了,只是判断条件有点多,细心就行了。

用pos[i][0]表示i的行数,用pos[i][1]表示i的列数(这样好判断一些),mapp[][]记录幻方(mapp防止与map重名)。

代码(我一开始竟然调了好久?!):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=45;
int mapp[N][N];
int pos[N*N][2];
int n;

void print() {
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=n;j++)
			printf("%d ",mapp[i][j]);
		printf("\n");
	}
}

int main() {
	//freopen("magic.in","r",stdin);
	//freopen("magic.out","w",stdout);
	scanf("%d",&n);
	pos[1][0]=1;pos[1][1]=(n+1)/2;mapp[pos[1][0]][pos[1][1]]=1;
	for(int i=2;i<=n*n;i++) {
		     if(pos[i-1][0]==1&&pos[i-1][1]!=n) pos[i][0]=n,pos[i][1]=pos[i-1][1]+1,mapp[pos[i][0]][pos[i][1]]=i;
		else if(pos[i-1][1]==n&&pos[i-1][0]!=1) pos[i][1]=1,pos[i][0]=pos[i-1][0]-1,mapp[pos[i][0]][pos[i][1]]=i;
		else if(pos[i-1][0]==1&&pos[i-1][1]==n) pos[i][1]=n,pos[i][0]=pos[i-1][0]+1,mapp[pos[i][0]][pos[i][1]]=i;
		else if(pos[i-1][0]!=1&&pos[i-1][1]!=n) {
			 if(!mapp[pos[i-1][0]-1][pos[i-1][1]+1]) pos[i][0]=pos[i-1][0]-1,pos[i][1]=pos[i-1][1]+1;
			 else pos[i][0]=pos[i-1][0]+1,pos[i][1]=pos[i-1][1];
			 mapp[pos[i][0]][pos[i][1]]=i;
		}
		//print();
	}
	print();
	return 0;
}


T2 信息传递:

2015的题真的很水。

核心就是找出最小环的长度。

扫描二维码关注公众号,回复: 56265 查看本文章

这道题做法很多,我的思路是删去入度为0的点,然后直接dfs跑一遍就行。其他方法大家可以百度。

友情链接:水友gay周的博客(标准做法)    顺便说一下rancy是他的女朋友。

代码(宇宙最简):

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int N=200000+233;
int n,in[N],a[N];
bool vis[N];

bool del() {
	bool re=false;
	for(int i=1;i<=n;i++)
		if(!in[i]&&!vis[i])
			re=true,in[a[i]]--,a[i]=-1,vis[i]=true;
	return re;
}

int dfs(int now,const int o) {
	if(now==o&&vis[o]) return 0;
	vis[now]=true;
	return dfs(a[now],o)+1;
}

int main() {
	//freopen("message.in","r",stdin);
	//freopen("message.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {
		scanf("%d",a+i);
		in[a[i]]++;
	}
	int ans=N+10;
	while(del());
	for(int i=1;i<=n;i++)
		if(!vis[i]) ans=min(ans,dfs(i,i));
	printf("%d",ans);
	return 0;
}

大家有空可以尝试并查集做法。


T3 斗地主:

输了地主赢了人生的我(隔壁赢了地主输了人生的佘刀已经die了)。

就是模拟题(Noip2015模拟题真的多)

大家可以认真思考下最优策略,然后dfs顺子的出牌方式就行了,具体方法大家自行百度吧。

多组数据忘了初始化ans的我已经哭晕在厕所了。。。我的AK啊!

代码(绝对良心):

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxx(a,b) a>b?a:b
#define minn(a,b) a<b?a:b
using namespace std;
int T,n,a[20],ans;

void init() {
	memset(a,0,sizeof(a));
	for(int num,opt,i=1;i<=n;i++) {
		scanf("%d%d",&num,&opt);
		if(num==0) a[14]++;
		if(num==1) a[12]++;
		if(num==2) a[13]++;
		if(num>=3) a[num-2]++;
	}
}

void solve(int x) {
	if(x>ans) return;
	int s1,s2,s3,s4;
	s1=s2=s3=s4=0;
	for(int i=1;i<=14;i++) {
		if(a[i]==1) s1++;
		if(a[i]==2) s2++;
	}
	for(int i=1;i<=14;i++) {
		if(a[i]==4) {
			s4++;
			if(s1>=2) s1-=2;
			else if(s2>=2) s2-=2;
			else if(s2>=1) s2-=1;
		}
	}
	for(int i=1;i<=14;i++) {
		if(a[i]==3) {
			s3++;
			if(s1>=1) s1-=1;
			else if(s2>=1) s2-=1;
		}
	}
	ans=min(ans,x+s1+s2+s3+s4);
	for(int i=1;i<=8;i++) {
		int j;
		for(j=i;j<=12;j++) {
			a[j]--;
			if(a[j]<0) break;
			if(j-i>=4) solve(x+1);
		}
		if(j==13) j--;
		while(j>=i) a[j--]++;
	}
	for(int i=1;i<=10;i++) {
		int j;
		for(j=i;j<=12;j++) {
			a[j]-=2;
			if(a[j]<0) break;
			if(j-i>=2) solve(x+1);
		}
		if(j==13) j--;
		while(j>=i) a[j--]+=2;
	}
	for(int i=1;i<=11;i++) {
		int j;
		for(j=i;j<=12;j++) {
			a[j]-=3;
			if(a[j]<0) break;
			if(j-i>=1) solve(x+1);
		}
		if(j==13) j--;
		while(j>=i) a[j--]+=3;
	}
}

int main() {
	//freopen("landlords.in","r",stdin);
	//freopen("landlords.out","w",stdout);
	scanf("%d%d",&T,&n);
	while(T--) {
		ans=23;
		init();
		solve(0);
		printf("%d\n",ans);
	}
	return 0;
}
最后祝大家早日AK!

猜你喜欢

转载自blog.csdn.net/y554280697/article/details/80062165