hdu6813.Last Problem

题目大意

一个无限大的平面,每次把一个格子变为x(x∈[1,n]),条件是四联通的格子中恰好出现了[x-4,x-1](忽视0和负数),求一种方案使得出现n

瞎搞历程

最后1h逐渐开始有人切,然后ymq开始生草报数

最后5min连挂三发(没输出+再交一遍+输出次数)后过了

题解

首先由于n很大并且操作次数是n^3级别的,所以可以感受到是一个可以持续且规律增长的东西

再感受一下应该是一个菱形/矩形不断扭动着往内缩,并且数不断增大的结构

可以手玩一下,发现标准的矩形和菱形都不行,因此一定是一个很奇怪但是很优美的东西

所以是这样构的:

用颜色代表数字可以很直观地感受到并且显著减少绘制复杂度

具体来说,按照红->橙->黄->绿->白的顺序放数即可

矩形大小开到100*100,能放则放,最后刚好可以剩下一个n

实现就根据数%5的余数决定开始的列,之后每下一行开始列+2取模

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;

int ans[100001][3],a[102][102],n,i,j,k,l,Ans,y;
bool bz[101],Bz;

void add(int x,int y,int s)
{
	if (x<1 || x>100 || y<1 || y>100) return;
	
	static int b[4],i;
	b[0]=a[x-1][y];
	b[1]=a[x+1][y];
	b[2]=a[x][y-1];
	b[3]=a[x][y+1];
	sort(b,b+4);
	
	fo(i,0,3) bz[b[i]]=1;
	Bz=1;
	fo(i,1,4)
	if (s-i>=1 && !bz[s-i])
	Bz=0;
	fo(i,0,3) bz[b[i]]=0;
	if (!Bz) return;
	
	++Ans;
	ans[Ans][0]=x;
	ans[Ans][1]=y;
	ans[Ans][2]=s;
	a[x][y]=s;
}

int main()
{
	#ifdef file
	freopen("12.in","r",stdin);
	freopen("12.out","w",stdout);
	#endif
	
	scanf("%d",&n);
	fo(i,1,100)
	{
		fo(j,1,100)
		add(i,j,1);
	}
	fo(l,2,n)
	{
		switch (l%5)
		{
			case 1:{y=1;break;}
			case 2:{y=2;break;}
			case 3:{y=5;break;}
			case 4:{y=4;break;}
			case 0:{y=3;break;}
		}
		fo(i,1,100)
		{
			for (j=y; j<=100; j+=5)
			add(i,j,l);
			y=(y+1)%5+1;
		}
	}
	
	fo(i,1,Ans) printf("%d %d %d
",ans[i][0],ans[i][1],ans[i][2]);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/gmh77/p/13405644.html