转载请注明出处:http://blog.csdn.net/jiangshibiao/article/details/21711819
【原题】
Fox Ciel wants to write a task for a programming contest. The task is: "You are given a simple undirected graph with n vertexes. Each its edge has unit length. You should calculate the number of shortest paths between vertex 1 and vertex 2."
Same with some writers, she wants to make an example with some certain output: for example, her birthday or the number of her boyfriend. Can you help her to make a test case with answer equal exactly to k?
The first line contains a single integer k (1 ≤ k ≤ 109).
You should output a graph G with n vertexes (2 ≤ n ≤ 1000). There must be exactly k shortest paths between vertex 1 and vertex 2 of the graph.
The first line must contain an integer n. Then adjacency matrix G with n rows and n columns must follow. Each element of the matrix must be 'N' or 'Y'. If Gij is 'Y', then graph G has a edge connecting vertex i and vertex j. Consider the graph vertexes are numbered from 1 to n.
The graph must be undirected and simple: Gii = 'N' and Gij = Gji must hold. And there must be at least one path between vertex 1 and vertex 2. It's guaranteed that the answer exists. If there multiple correct answers, you can output any of them.
2
4 NNYY NNYY YYNN YYNN
9
8 NNYYYNNN NNNNNYYY YNNNNYYY YNNNNYYY YNNNNYYY NYYYYNNN NYYYYNNN NYYYYNNN
1
2 NY YN
In first example, there are 2 shortest paths: 1-3-2 and 1-4-2.
In second example, there are 9 shortest paths: 1-3-6-2, 1-3-7-2, 1-3-8-2, 1-4-6-2, 1-4-7-2, 1-4-8-2, 1-5-6-2, 1-5-7-2, 1-5-8-2.
【大意】给定一个K,让你构造一个01的邻接矩阵,使得从1号点到2号点的最短路径的条数为K。K<=10^9,但是构造的点数必须小于等于1000.
【分析】刚开始的思路是这样的:
像满二叉树一样画。但是随后发现这样有点问题:因为这是满足加法原理的,路径条数和最后一排孩子的节点数一样。
之后小RZZ给出正确的思路:
我们把最短路径的条数转化成二进制。如21。然后先在上面构造路径条数为P的图(P是不超过K的最大的2的幂次方)然后根据二进制的01规律,我们在1的位置同上面连一条边(图中蓝色)
编好后发现还有一个问题:这样,上下两种路的路径长度不同!于是可以把1的位置移到下面来,并在下面那条路的每一条边上再各添一个点,长度就相同了。
【代码】
#include<cstdio>
#include<algorithm>
using namespace std;
int k,cnt,i,t,last1,last2,now,j;
int a[1001];
bool f[1001][1001];
int main()
{
scanf("%d",&k);
while (k)
{
a[++cnt]=k%2;
k/=2;
}
for (i=1;i<=cnt/2;i++) {t=a[i];a[i]=a[cnt-i+1];a[cnt-i+1]=t;}
now=3;f[1][3]=true;last1=3;last2=1;
for (i=2;i<=cnt;i++)
{
f[last1][++now]=true;
f[last1][++now]=true;
now++;last1=now;
f[now-2][now]=true;
f[now-1][now]=true;
f[last2][++now]=true;
f[now][now+1]=true;now++;
if (a[i]) f[now-2][now]=true;
last2=now;
}
f[last1][2]=true;
printf("%d\n",now);
for (i=1;i<=now;i++)
{
for (j=1;j<=now;j++)
{
if (f[i][j]) f[j][i]=true;
if (f[j][i]) f[i][j]=true;
if (f[i][j]) printf("Y");else printf("N");
}
printf("\n");
}
}