[USACO 6.5.1]All Latin Squares

题解

  搜索剪枝.

  置换圈个数相同及对应的置换圈内元素个数相同即视为相同方案.

代码

/*
TASK:latin
LANG:C++
*/
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

int n, s[10][10], fact[] = {1, 1, 2, 6, 24, 120, 720, 5040};
bool row[10][10], col[10][10];
long long f[10][100];

long long dfs(int x, int y)
{
    if (x == n) return 1;
    int totn = 0, totlen = 1;
    if (x == 3 && y == 2)
    {
        int v[10];
        memset(v, true, sizeof(v));
        for (int i = 1; i <= n; ++i)
            if (v[i])
            {
                int len = 0, st = i;
                totn++;
                for (;;)
                {
                    len++;
                    v[st] = false;
                    st = s[2][st];
                    if (!v[st]) break;
                }
                totlen *= len;
            }
        if (f[totn][totlen] != -1) return f[totn][totlen];
    }
    long long ans = 0;
    for (int i = 1; i <= n; ++i)
        if (row[x][i] && col[y][i])
        {
            row[x][i] = col[y][i] = false;
            s[x][y] = i;
            if (y == n) ans += dfs(x + 1, 2);
            else ans += dfs(x, y + 1);
            row[x][i] = col[y][i] = true;
        }
    if (x == 3 && y == 2) return f[totn][totlen] = ans;
    else return ans;
}

int main()
{
    freopen("latin.in", "r", stdin);
    freopen("latin.out", "w", stdout);
    scanf("%d", &n);
    memset(row, true, sizeof(row));
    memset(col, true, sizeof(col));
    for (int i = 1; i <= n; ++i)
    {
        row[i][i] = false;
        col[i][i] = false;
        s[1][i] = s[i][1] = i;
    }
    memset(f, -1, sizeof(f));
    cout << dfs(2, 2) * fact[n-1] << endl;
    return 0;
}
时间: 2024-11-02 22:34:11

[USACO 6.5.1]All Latin Squares的相关文章

USACO 6.5 All Latin Squares

All Latin Squares A square arrangement of numbers 1 2 3 4 5 2 1 4 5 3 3 4 5 1 2 4 5 2 3 1 5 3 1 2 4 is a 5 x 5 Latin Square because each whole number from 1 to 5 appears once and only once in each row and column. Write a program that will compute the

Gym 100496A Avangard Latin Squares(矩阵游戏)

题意:输入一个n,表示在n*n的矩阵中填1~n,使每行每列以及所有正对角线所有反对角线均出现1~n一次.若存在,输出Yes和矩阵,否则输出No; 思路:比赛的时候没思路.将1~n换为0~n较好处理一些.先只考虑0的位置,每行将0向一个方向移动固定格子数,枚举所需的移动步数, 若满足条件(无同行同列同对角线)则Yes,1~n以相同步数移动:否则为No; #include<cstdio> #include<cstring> #include<algorithm> using

[转]100个经典C语言程序(益智类问题)

目录: 1.绘制余弦曲线 2.绘制余弦曲线和直线 3.绘制圆 4.歌星大奖赛 5.求最大数 6.高次方数的尾数 8.借书方案知多少 9.杨辉三角形 10.数制转换 11.打鱼还是晒网 12.抓交通肇事犯 13.该存多少钱 14.怎样存钱利最大 15.捕鱼和分鱼 16.出售金鱼 1.7 分数四则运算 17.平分七筐鱼 18.有限5位数 19. 8 除不尽的数 21.4位反序数 22.求车速 23.阿姆斯特朗数 24.完全数 26.亲密数 27.自守数 28.回文数 29.求具有abcd=(ab+c

[转]100个经典C语言程序

本文转载自:http://blog.sina.com.cn/s/articlelist_1615065844_0_1.html 1.绘制余弦曲线 在屏幕上用“*”显示0~360度的余弦函数cos(x)曲线*问题分析与算法设计如果在程序中使用数组,这个问题十分简单.但若规定不能使用数组,问题就变得不容易了. 关键在于余弦曲线在0~360度的区间内,一行中要显示两个点,而对一般的显示器来说,只能按行输出,即:输出第一行信息后,只能向下一行输出,不能再返回到上一行. 为了获得本文要求的图形就必须在一行

魔术师发牌和拉丁方阵

本文利用经典的魔术师发牌问题与拉丁法阵分别解说了循环链表与单向链表的使用,作为算法中的经典,对于链表的学习和理解都有着非常大的帮助,最好还是一看. 魔术师发牌问题 问题描写叙述: 魔术师利用一副牌中的13张黑牌,预先将他们排好后叠放在一起,牌面朝下.对观众说:"我不看牌,仅仅数数就能够猜到每张牌是什么,我大声数数,你们听,不信?现场演示."魔术师将最上面的那张牌数为1,把他翻过来正好是黑桃A,将黑桃A放在桌子上,第二次数1,2,将第一张牌放在这些牌的以下,将第二张牌翻过来,正好是黑桃2

《高级语言程序设计》习题集

<高级语言程序设计>习题集 (本资料仅供学生学习使用) ? ? 求最大数 借书方案知多少 杨辉三角形 数制转换 打鱼还是晒网 该存多少钱 怎样存钱利最大 出售金鱼 平分七筐鱼 有限5位数 8 除不尽的数 一个奇异的三位数 4位反序数 求车速 阿姆斯特朗数 完全数 亲密数 回文数 求素数 求具有abcd=(ab+cd)2性质的四位数 歌德巴赫猜想 百钱百鸡问题 爱因斯坦的数学题 换分币 年龄几何 三色球问题 马克思手稿中的数学题 最大公约数和最小公倍数 分数比较 分数之和 将真分数分解为埃及分数

拉丁矩阵

#include <stdio.h> #define N 6                                             /*确定N值*/ int main1() { int i, j, k, t; printf( "The possble Latin Squares of order %d are:\n", N ); for ( j = 0; j < N; j++ )                       /*构造N个不同的拉丁方阵

Generalizing RDP Codes Using the Combinatorial Method

摘要 本文提出了PDHLatin,它是一种基于列汉密尔顿拉丁方(CHIS-column hamiltonian Latin squares)构造的校验块独立的2容错水平码.通过证明它是MDS码. 本文也提出了一种新的基于CHIS的校验块独立的2容错混合编码-PIMLatin. 这两种编码具有良好的扩展性以及结构多样性. 同时本文也讨论编码缩减技术,以及它所带来的参数扩展性,结构可变性和可靠性的提升. 基于垂直缩减的思想,本文利用非汉密尔顿拉丁方的方式提出了一种2容错阵列码的构建方式. 简介 磁盘

100个经典C语言程序(益智类)

100个经典C语言程序(益智类) [1.绘制余弦曲线] 在屏幕上用"*"显示0~360度的余弦函数cos(x)曲线 [问题分析与算法设计] 利用cos(x)的左右对称性,将屏幕的行方向定义为x,列方向定义为y,则0~180度的图形与180~360度的图形是左右对称的,若定义图形的总宽度为62列,计算出x行0~180度时y点的坐标m,那么在同一行与之对称的180~360度的y点的坐标就 应为62-m.程序中利用反余弦函数acos计算坐标(x,y)的对应关系. #include<st