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\n",ans[i][0],ans[i][1],ans[i][2]);
fclose(stdin);
fclose(stdout);
return 0;
}