UVa 269 Counting Patterns 解题报告(暴力)

    UVa上看不到题目了,可以在UVa Live上或者VJudge上看题目。这里贴个:

Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu

[]   [Go Back]   [Status]  

Description

Download as PDF


 Counting Patterns 

Let n and k be numbers with n > 0 and tex2html_wrap_inline36 . A configuration of the n-k-puzzle is an n-tuple with elements in the range tex2html_wrap_inline44 such that their sum is zero. Configurations are considered equivalent when they can be obtained from each other by (a) cyclic permutation of the tuple over one or more positions, (b) reversal of the tuple, (c) sign reversal of all elements, or (d) combinations of (a), (b), and (c). Equivalence classes are called patterns.

For instance, (0, 1, 1, -2) is a configuration of the 4-2-puzzle. Some equivalent configurations are: (a) (1, -2, 0, 1), (b) (-2, 1, 1, 0), (c) (0, -1, -1, 2), and (d) (-1, -1, 0, 2). Below is given a list of (the lexicographically largest) representatives of the 14 patterns of the 4-2-puzzle.

displaymath46

Your program computes the number of patterns for a sequence of n-k-puzzles. And output the list of patterns (represented by the largest one in the patterns), from lower order to higher one.

Input

The input consists of a sequence of pairs of integers n and k, which are separated by a single space. Each pair appears on a single line. The input is terminated by an end-of-file. The value for n + k is at most 12. Make sure that your algorithm is fantastic enough.

Output

The output contains a sequence of blocks, the fisrt line contain a single integer(x), representing the number of patterns for the corresponding n-k-puzzles in the input, and follow x lines, each one contain one pattern(from lower order to higher one). Print one blank line between two consecutive blocks. No blank line should appear at the end of the output.

Sample Input

8 0
4 2

Sample Output

1
(0,0,0,0,0,0,0,0)

14
(0,0,0,0)
(1,-1,1,-1)
(1,0,-1,0)
(1,0,0,-1)
(1,1,-1,-1)
(2,-2,2,-2)
(2,-1,0,-1)
(2,-1,1,-2)
(2,0,-2,0)
(2,0,-1,-1)
(2,0,0,-2)
(2,1,-2,-1)
(2,1,-1,-2)
(2,2,-2,-2)

[]   [Go Back]   [Status]  

    解题报告:求出所有的,n个绝对值不大于k的数的排列,排列的和为0。且对于一个排列,全部正负号翻转、排列顺序翻转、起点移动到末尾构造出来的新排列视为同一个排列。要求按照字典序打印所有的排列。

    刚开始的想法是:先构造出所有和为0的无序的n个数,根据这个来构造出所有可能的排列。不过TLE了。

    参考了神牛们的解题报告,模仿之……其思路是按照字典序构造出和为0的排列,检查对于所有可能的变换操作,该排列是否是最优的。是的话就记录下来。最后打印。简单暴力,但是很有效。代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
using namespace std;
#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define bit(n) (1LL<<(n))
typedef long long LL;
typedef unsigned long long ULL;
void work();
int main()
{
#ifdef ACM
//    freopen("in.txt", "r", stdin);
#endif // ACM
    work();
}

/***************************************************/

const int maxn = 101010;
int cnt;
int res[maxn][20];
int a[20], b[40];
int n, k;

bool bigger(int * a, int * b)
{
    ff(i, n) if(a[i] != b[i])
        return a[i] > b[i];
    return false;
}

void check()
{
    ff(i, n)
        b[i] = b[i+n] = a[i];
    ff(i, n) if(b[i] == a[0])
        if(bigger(b+i, a)) return;
    reverse(b, b+2*n);
    ff(i, n) if(b[i] == a[0])
        if(bigger(b+i, a)) return;

    ff(i, n)
        b[i] = b[i+n] = -a[i];
    ff(i, n) if(b[i] == a[0])
        if(bigger(b+i, a)) return;
    reverse(b, b+2*n);
    ff(i, n) if(b[i] == a[0])
        if(bigger(b+i, a)) return;

    memcpy(res[cnt++], a, sizeof(a));
}

void dfs(int pos, int sum)
{
    if(pos == n)
    {
        if(sum == 0)
            check();
        return;
    }

    if(abs(sum) > (n-pos)*a[0]) return;

    for(a[pos] = -a[0]; a[pos] <= a[0]; a[pos]++)
    {
        if(a[pos-1] == a[0] && a[pos] > a[1]) return;
        dfs(pos+1, sum + a[pos]);
    }
}

void work()
{
    int first = false;
    while(scanf("%d%d", &n, &k) == 2)
    {
        cnt = 1;
        for(a[0] = 1; a[0] <= k; a[0]++)
            dfs(1, a[0]);

        if(first) puts("");
        first = true;
        printf("%d\n", cnt);
        ff(i, cnt)
        {
            printf("(%d", res[i][0]);
            fff(j, 1, n-1) printf(",%d", res[i][j]);
            puts(")");
        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章