这道题居然写了一晚上,开始的思路就对,但是处理还是欠缺经验。
思路:
将每个数分成二进制。将最大的2^i的i画成2*2*2*...*2有i个2组的点全连接。那么就可以得到2^i条边。对于每一个数分解成二进制都是2^i1+2^i2+2^i3...(i1>i2>i3>...)对于剩下的i2...in 只需要在之前弄好的图上在某个位置加上一个一个的点使其从1到2的距离相同就好~。我开始一直RE在35组数据上,就是没有在原图上面加点,而是有重新画图。使得节点超1000了。
input为6,示例如下:
代码:
#include<cstdio>
using namespace std;
int f[35];
char s[1001][1001];
void ini(){
f[0]=1;
for(int i=1;i<=29;i++){
f[i]=f[i-1]*2;
}
}
main(){
int n;
ini();
while(scanf("%d",&n)!=-1){
for(int i=0;i<1000;i++){
for(int j=0;j<1000;j++){
s[i][j]='N';
}
}
int num=2,cnt=n,p=1;
int max=0,pre=0;
for(int i=29;i>0;i--){
if(cnt/f[i]!=0){
//printf("peach:%d",p);
if(max==0){
max=i;
num+=i*2;
s[0][++p]='Y';
s[p][0]='Y';
s[0][++p]='Y';
s[p][0]='Y';
pre=p-1;
for(int j=i-1;j>0;j--){
s[pre][++p]='Y';
s[p][pre]='Y';
s[pre+1][p]='Y';
s[p][pre+1]='Y';
s[pre][++p]='Y';
s[p][pre]='Y';
s[pre+1][p]='Y';
s[p][pre+1]='Y';
pre=p-1;
}
}
// pre=1+i*2;
if(max-i>0){
pre=i*2;
num+=max-i;
s[pre][++p]='Y';
s[p][pre]='Y';
s[pre+1][p]='Y';
s[p][pre+1]='Y';
pre=p;
for(int j=max-i-1;j>0;j--){
s[pre][++p]='Y';
s[p][pre]='Y';
pre=p;
}
s[1][pre]='Y';
s[pre][1]='Y';
}
else{
s[1][pre]='Y';
s[pre][1]='Y';
s[1][pre+1]='Y';
s[pre+1][1]='Y';
}
}
cnt=cnt%f[i];
}
if(cnt!=0){
//printf("max:%d p:%d\n",max,p);
pre=0;
num+=max;
for(int i=0;i<max;i++){
//printf(" pre: %d pp:%d\n",pre,p);
s[pre][++p]='Y';
s[p][pre]='Y';
pre=p;
}
//printf("%d\n",pre);
s[pre][1]='Y';
s[1][pre]='Y';
}
printf("%d\n",num);
for(int i=0;i<num;i++){
for(int j=0;j<num;j++){
printf("%c",s[i][j]);
}
printf("\n");
}
}
}