集训2020.01.18【NOIP提高组】模拟B 组分析反思(【东莞市选2009】9数字 原子核研究 探险者拉罗 【NOIP2014八校联考第3场第1试10.4】选择困难症)

这次比赛打炸了,67.5分,36名,垫底~~~最近我变水了,突然智商下降,再也找不到以前的感觉,陷入小低谷……

T1:【东莞市选2009】9数字,很简单的一道搜索题目。没想到比赛时居然打崩了,把枚举的范围打小了,答案错误37.5。比赛时没来得及检查,也促成了这一事故。总结:以后比赛无论题打没打完,最后15分钟一定要耐心检查。

T2:【东莞市选2009】原子核研究,比赛时,越看越像数据结构,这题的最关键之处在于最小的质量差怎么解决,如果换作是最小值最大值那么人人都能切,打个线段树就解决的问题,于是比赛时想质量不大于100000的正整数,可以每一个质量的原子核都开一个点,那关键就在于怎么维护最小差值了,但是脑子却又卡死了,并没有结果,果断放弃,最后匆匆忙忙打了个最暴力的暴力,那了37.5分。正解:事实证明,我比赛时那很快就被我kill掉的思想没错。

对于每一个质量原子核,维护三个值——max,min,mif(表示最小差值),那么对于每一个区间[l,r]最小差值,可以由

一、[l,mid]中存在的最大的质量与[mid+1,r]的点中存在的最小的质量的差值

二、[1,mid]的最小差值

三、[mid+1,r]的最小差值

更新。

总结:对于某些题,我们可以将之转换(对于这题可以转换为求最大/小值),然后通过转换后的出的结果得到我们最终要求的结果。

T3:【东莞市选2009】探险者拉罗 ,这题,比赛时第一眼看上去想一道BFS水题,但仔细一想,却又显得有点艰难——状态太多了,比赛时想到的记录状态F[1..100 n][1..100 m][0..16 g经过的藏金点数][0..200当前连续潜行的距离],但是如果采用这种,会出现错误,一个藏金点被多次经过只算一个,那么,我就尝试加一维状压来解决,但显然会空超,于是放弃,比赛时状压DP在我脑子里一闪而过。正解:被我kill掉的状压DP,f[s][i],s表示当前经过了哪些点,当前在i这个点,f表示最小总潜行时间。首先用某算法(如dijk、「推荐」BFS求出两两点之间的最短距离),然后就是状压DP了——特别注意!!!f[s][i]可以由f[s][j](i!=j)转换而来。总结:对于一些较复杂的看起来想BFS的“迷宫”题目,可以对其中的某个状态用状压DP解决,特别是特别小的情况。
贴上code,这题有很多细节:

#include
#include
using namespace std;
int n,m,dis[20][20],bh[105][105],f[262144][20],stx,sty,enx,eny,sumg,head,tail,d[1000000][4],xy[20][2],tt,t,ans1,ans2,sum1,xx,yy;
const int fx[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
bool bz[105][105];
char ch,map[105][105];
inline void bfs(int x){
	head=0;
	tail=1;
	d[1][0]=0;
	d[1][3]=0;
	d[1][1]=xy[x][0];
	d[1][2]=xy[x][1];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			bz[i][j]=0;
	bz[xy[x][0]][xy[x][1]]=1;
	do{
		head++;
		for(int i=0;i<4;i++){
			xx=d[head][1]+fx[i][0];
			yy=d[head][2]+fx[i][1];
			if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&!bz[xx][yy]&&map[xx][yy]!='#'&&d[head][3]<=m){
				tail++;
				if(map[xx][yy]!='-') d[tail][3]=0,d[tail][0]=d[head][0];
				else d[tail][3]=d[head][3]+1,d[tail][0]=d[head][0]+1;
				d[tail][1]=xx;
				d[tail][2]=yy;
				bz[xx][yy]=1;
				if(map[xx][yy]!='-')
					dis[bh[xx][yy]][x]=dis[x][bh[xx][yy]]=min(dis[x][bh[xx][yy]],d[tail][0]);
			}
		}
	}while(head0&&f[s][i]<0x3f3f3f3f)
				for(int j=sumg+2;j>=1;j--)
					f[s|(1<<(j-1))][j]=min(f[s|(1<<(j-1))][j],f[s][i]+dis[i][j]);
	}
	ans2=0x3f3f3f3f;
	for(int s=2;s<=(1<<(sumg+2))-1;s++)
		if((s&1)>0&&(s&2)>0){
			sum1=0;
			for(int j=3;j<=sumg+2;j++)
				if((s&(1<<(j-1)))>0) sum1++;
			if(sum1>ans1&&f[s][2]<0x3f3f3f3f){
				ans1=sum1;
				ans2=f[s][2];
			}
			if(sum1==ans1&&f[s][2]


T4:比赛时以为这题要用什么数据结构,于是果断放弃,打了个排序暴力。正解:题解给出了两个AC方法——1、堆heap 2、第k短路,同学们还有一种做法3、二分+搜索(剪枝)但是比赛完实现的过程发现1方法我可能出现了理解性偏差,会出现重复的情况。

你可能感兴趣的:(OI,#,比赛)