zoukankan      html  css  js  c++  java
  • UVa OJ 135 No Rectangles (没有矩形)

    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
    解答

    #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;
    }
    



    知识共享许可协议 作者:王雨濛;新浪微博:@吉祥村码农;来源:《程序控》博客 -- http://www.cnblogs.com/devymex/
    此文章版权归作者所有(有特别声明的除外),转载必须注明作者及来源。您不能用于商业目的也不能修改原文内容。
  • 相关阅读:
    [Step By Step]SAP Visual intelligence连接到SAP HANA并访问视图 沧海
    SAP HANA中的用户拷贝(User Copy) 沧海
    在Cloudshare上使用PAL=〉系统检查及初始化 沧海
    SAP HANA学习资料中的基础表及数据SQL语句汇总 沧海
    [Step By Step]SAP HANA PAL多用户使用(单指数平滑法SINGLESMOOTH) 沧海
    [Step By Step]SAP HANA中创建层次分析视图(Hierarchy Analytic View) 沧海
    [Step By Step]SAP Visual Intelligence新增公式数据列(SAP HANA中提取数据) 沧海
    SAP HANA Education: Course & Certification Program 2013(SAP HANA认证考试) 沧海
    [Step By Step]SAP HANA中创建分析权限(Analytic Privilege) 沧海
    SAP HANA 存储过程中的IF While使用案例 沧海
  • 原文地址:https://www.cnblogs.com/devymex/p/1804917.html
Copyright © 2011-2022 走看看