(接上题,反正是一起做的那么故事情节也接上吧嘻嘻嘻)
“正好,带我去一趟天线崖。”
”你确定?!你都说了都要暴雨了,前几天的暴雨……“
”是啊,你还抱怨整天闷在家里啥事也没干呢,结果就剩下我在刷题而你整天再睡觉。“
因为山脉的阻隔,所以他们只能乘坐小船到达那里。
而给他们租小船的人,开出了很高的价钱,但是。
”你们帮我解决一个问题,我就免费带你们去你们想去的地方。“
他指了指酒馆前面做的一个汉子,汉子的桌子上摆着一个很大的六边形棋盘。
————————————————————————
时间限制: 1S 空间限制:256M
棋盘是由许多个六边形构成的,共有5种不同的六边形编号为1到5,棋盘的生成规
则如下:
1.从中心的一个六边形开始,逆时针向外生成一个个六边形。
2.对于刚生成的一个六边形,我们要确定它的种类,它的种类必须满足与已生成的相
邻的六边形不同。
3.如果有多个种类可以选,我们选择出现次数最少的种类。
4.情况3下还有多个种类可以选,我们选择数字编号最小的。
现在要你求第N个生成的六边形的编号。
输入格式:
第一行:T,表示数据组数
接下来T行,每行一个数:N,表示第N个六边形
输出格式:
共t行,每行一个数,表示第N个数据的答案
样例输入:
4
1
4
10
100
样例输出:
1
4
5
5
数据范围:
100%数据满足
1<=T<=20
1<=N<=10000
30%数据满足
1<=N<=100
————————————————
今天的模拟都很有意思?!
这道明显是找规律的题却意外的不好找规律。
思考一下,恩……大概是六边形使我们石乐志。
但是大家的普遍打法都是靠六边形转换成矩形,然后打表。
我们想一想……
这道题难道真的无规律可循吗?!
当答案找不到规律时,我们想想能够导出答案的东西是否有规律。
是啊,如果我们知道每一个六边形的相邻情况的话完全模拟就可以解决啊!
这就是规律:
遵从题意,我们从起点开始,按放数字的顺序依次编号为1,2……
接下来,我们知道与1相邻的有2,3,4,5,6,7
那么因为1相邻着2,所以2相邻着1
又因为2肯定相邻着3
所以与2相邻有1,3
然而还差四个点为7,8,9,10
好的上述的内容总结为三条规律:
对于点i,找到与它所有相邻的六个点
已知i-1的点所邻的最大编号的点为k
1.从1~i-1,如果有与i相邻的点,就加上
2.i+1一定与i相邻
3.上述两步操作完后所得的相邻点的个数为n<6,那么接下来的点分别为k+0,k+1……直到n==6为止
其实我们还可以证明这个的正确性(然而再写下去我的手就抽筋了,证明就交给大家了?)
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
int l[10001][7]={0};
int f[10001]={0};
int cnt[6]={0};
int ji[10001]={0};
bool ok[10001]={0};
void chu(){
for(int i=1;i<=6;i++){
l[1][i]=i+1;
}
ok[1]=1;
for(int i=1;i<=10000;i++){
if(ok[i]==1){
for(int j=1;j<=6;j++){
int k=l[i][j];
if(k>10000||ok[k]==1)continue;
ji[k]++;
l[k][ji[k]]=i;
if(ji[k]==6)ok[k]=1;
}
}else{
ji[i]++;
l[i][ji[i]]=i+1;
if(ji[i]==6){
ok[i]=1;
i--;
continue;
}else{
int hah=0;
for(int j=ji[i]+1;j<=6;j++){
l[i][j]=l[i-1][6]+hah;
hah++;
}
}
ji[i]=6;ok[i]=1;
i--;
}
}
return;
}
bool ha[7];
int main(){
freopen("hex.in","r",stdin);
freopen("hex.out","w",stdout);
chu();
int t;
scanf("%d",&t);
int maxn=1;
while(t--){
int n;
scanf("%d",&n);
if(f[n]!=0){
printf("%d\n",f[n]);
continue;
}else{
for(int i=maxn;i<=n;i++){
memset(ha,0,sizeof(ha));
for(int j=1;j<=6;j++){
if(l[i][j]>10000)continue;
ha[f[l[i][j]]]=1;
}
int minn=2147483647;
for(int j=1;j<=5;j++){
if(ha[j]==0){
minn=min(minn,cnt[j]);
}
}
for(int j=1;j<=5;j++){
if(ha[j]==0&&minn==cnt[j]){
f[i]=j;
cnt[j]++;
break;
}
}
}
}
printf("%d\n",f[n]);
maxn=max(maxn,n+1);
}
return 0;
}