程序控

IPPP (Institute of Penniless Peasent-Programmer) Fellow

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::
  75 随笔 :: 0 文章 :: 470 评论 :: 116万 阅读
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

Problem
问题

Consider a grid such as the one shown. We wish to mark k intersections in each of n rows and n columns in such a way that no 4 of the selected intersections form a rectangle with sides parallel to the grid. Thus for k = 2 and n = 3, a possible solution is:
想象一个n行n列的网格,我们要在每行每列都标注k个交点,使得这些交点中的任意4个所构成的矩形(如果可以构成矩形),都不存在与网格线平行的边。比如k=2和n=3的情况,可能的解如下:

 

f1

 

It can easily be shown that for any given value of k, k2-k+1 is a lower bound on the value of n, and it can be shown further that n need never be larger than this.
易知,对于任意的k,n的最小值为:k2-k+1。更进一步来讲,n也不会比这个值更大。

Write a program that will find a solution to this problem for k32, k-1 will be 0, 1 or prime.
写一个程序,计算所有k≤32的解。k-1可能是0,1或任何素数。

 

Input and Output
输入与输出

Input will consist of some values for k, one of each line. For each value of k, output will consist of n lines of k points indicating the selected points on that line. Print a blank line between two values of k.
输入包括一组k的值,每个一行。对每一个k值,要输出n行数,各行中的每个数代表在该行中选择的交点编号。每组k值的输出之间要有一个空行。

 

Sample input
输入示例

2
1

 

Sample output
输出示例

1 2
1 3
2 3

1

 

Analysis
分析

有趣的找规律题目,我想不会有人用递归的办法去暴力破解吧?一拿到题,我当时就懵了,想了好久没有理出头绪来。后来觉得光靠空想根本不可能解决问题,便找来尘封已久的棋盘来摆了一下,结果豁然开朗。强烈建议您先别急着看解析,想办法摆一下棋盘,或着在坐标纸上画一下。这是个锻炼思维的好机会,直接看解析就很没意思了。

摆的方法是非常直接的,第一行直接摆在前面,下面每行在不于上面的行冲突(构成矩形)的情况下,尽量往前摆就OK了。下图是k=5的情况:

 

f1

 

仔细看看,应该发现规律了吧。还没有?再看下图:

 

f2

 

从第6行开始,以下每4行为一组,每组编号用i表示,i=(0, 1, 2, 3);每组中的4行用j表示,j=(0, 1, 2, 3);每行中从第6列开始,右边每4列为一组,每组编号用s表示,s=(0, 1, 2, 3)。这里用s是为了避免和上面已经出现的k产生混淆。

(i, j, s)为一个三元组,现在要求的就是(0, 0, 0)到(3, 3, 3),一共4×4×4=64个值。i=0时,规律很明显,(0, j, s)=5 + s * (k - 1) + 1。式中第一个5是空出前面的5个格,s * (k - 1)计算当前4×4方块的起点,后面加1是为了保证数字从1开始,而不是0。

再看(1, 0, k)到(2, 0, k),第一个4×4方块(橙色)和上面的(黄色)排列是一样的,只是第二个方块(蓝色)比上面的(青色)向右移动了一格。由此可推知公式:

  • (j + (s * i)) % m + s * m + k + 1

再用下面的两排验证此公式,都成功。现在才明白为什么n=k2-k+1,原来n=k+(k-1)(k-1),展开即得原式。这道题虽然解开了,但是这个公式我没有能够证明,这里面可能还蕴涵着更深奥的数理逻辑问题。如果您知其所以然,望不吝赐教!

 

Solution
解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
using namespace std;
//主函数
int main(void) {
    //循环处理每一组输入
    for (int k, nFirst = 1; cin >> k; nFirst = 0) {
        //不是第一次输出时,前面要加空行
        if (nFirst == 0) {
            cout << endl;
        }
        int m = k - 1;
        //输出头部的k行
        for (int i = 0; i < k; ++i) {
            cout << 1;
            for (int j = 1; j < k; ++j) {
                cout << ' ' << i * m + j + 1;
            }
            cout << endl;
        }
        //以下算法请参照图示及相关文档
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < m; ++j) {
                cout << i + 2;
                for (int s = 0; s < m; ++s) {
                    cout << ' ' << (j + (s * i)) % m + s * m + k + 1;
                }
                cout << endl;
            }
        }
    }
    return 0;
}
posted on   Devymex  阅读(1589)  评论(0编辑  收藏  举报
编辑推荐:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
阅读排行:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
点击右上角即可分享
微信分享提示