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(")");
        }
    }
}


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