timus_1692
各省的旗子
题目意思:有n种颜色,需要用这n种颜色为某个国家的各省创建旗子,并满足条件:每个省的旗子至少有一种公共的颜色,每种颜色不会同时出现在三个或更多的旗子上。求满足上面条件能创建的最多的旗子数。
输入:n(3 ≤ n ≤ 1000)
输出:第一行输出旗子数k,接下来的k行输出每面旗子中包含的颜色个数和颜色编号(1,2,3...n),它们之间用空格隔开。这样的解可能会有多个,只要其中的一种就可以了。
样例输入:
4
样例输出:
3
2 1 2
2 1 3
2 2 3
思路:
通过题目意思可以理解到每面旗子要与其他旗子至少有一种公共的颜色,而且这些公共颜色是不同的,所以假设最多能创建k面旗子,那么每面旗子至少要有k-1种颜色,只有这样才能满足题目条件。每种颜色不会同时出现在三个或更多的旗子上可以知道一种颜色在k面旗子中最多出现2次,所以k面旗子最多使用2*n种颜色。所以满足k*(k-1) <= 2*n就可以了,求这个不等式的最大正整数解就是我们要求的k。我们可以用一种比较简单的方法求这个解,先对2*n开方,取它的下界为k,只要k满足k*(k-1) <= 2*n,就递增k,这样就可以找到这个最大解了。
其次是怎么构造这个解,我的方法是每面旗子直接就k-1种颜色,最简单也最容易构造。先对第1面旗子分配编号为1,2,3...k-1的颜色,同时把1,2,3...k-1编号的颜色分别分给第2、第3、第4...第k面旗子,然后对第二面旗子分配编号为k,k+1,k+2...k+k-2,同时把k,k+1,k+2...k+k-2编号的颜色分别分给第3、第4、第5...第k面旗子,重复这个过程直到第k面旗子。
源代码:
1 #include <stdio.h> 2 #include <math.h> 3 4 int n; 5 int ans[50][50]; 6 int k; 7 8 int main(void) 9 { 10 int i, j, ii, jj, base; 11 12 scanf("%d", &n); 13 k = (int)sqrt(2 * n); 14 while (k * (k - 1) <= 2 * n) 15 k ++; 16 k --; 17 i = 1; 18 ii = k - 1; 19 base = 0; 20 for (j = 1; j <= k && i <= n; j ++) 21 { 22 for (jj = j + base; jj <= k - 1 + base && i <= n; jj ++) 23 { 24 ans[j][jj] = i; 25 ans[jj - base + 1][j + base] = i ++; 26 } 27 } 28 printf("%d\n", k); 29 for (i = 1; i <=k; i ++) 30 { 31 j = 1; 32 while (ans[i][j]) 33 j ++; 34 printf("%d ", j - 1); 35 for (ii = 1; ii < j; ii ++) 36 printf("%d ", ans[i][ii]); 37 printf("\n"); 38 } 39 return 0; 40 }