您的位置:首页 > 其它

UVA - 269 Counting Patterns 构造

2015-04-21 11:04 176 查看
ACM Contest Problems Archive University of Valladolid (SPAIN)
269 Counting Patterns
Let n and k be numbers with n > 0 and k  0. A con guration of the n-k-puzzle is an n-tuple with
elements in the range k
: : k such that their sum is zero. Con gurations 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 con guration of the 4-2-puzzle. Some equivalent con gurations 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.

(0; 0; 0; 0) (2; 2;

2; 2)

(2; 0; 0; 2)

(1; 1;

1; 1)

(2; 1;

0; 1)

(2; 1; 2;

1)

(1; 0; 1;

0) (2; 1;

1; 2)

(2; 1; 1;

2)

(1; 0; 0; 1)

(2; 0; 2;

0) (2; 2; 2;

2)

(1; 1; 1;

1)

(2; 0; 1;

1)

Your program computes the number of patterns for a sequence of n-k-puzzles.

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- le. The value for n + k is at

most 11.

Output

The output contains a sequence of integers, each on one line, representing the number of patterns for

the corresponding n-k-puzzles in the input. No blank line should appear at the end of the output.

Sample Input

8 0

4 2

Sample Output

1

14

解题思路:其实这题的题目是错误的,这题要求输出的是所有集合,且按字典序从小到大排。

所有的集合肯定是由m个集合演变而来的,且这些集合没有交集,所以只要取出这些集合的最大字典序的就可以

枚举的时候从1开始枚举,因为经过取反后,除了都是0的集合外,其他的集合中必有一个数是大于等于1的,所以直接从1开始枚举

给出学长的题解:

< /article/2061702.html />

[code]#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define maxm 100005
#define maxn 15
int a[maxn], s[maxm][maxn], b[maxn * 2],  n, k, ans;

void put(int num[]) {
    printf("(%d", num[0]);
    for(int i = 1; i < n; i++)
        printf(",%d", num[i]);
    printf(")\n");
} 

bool judge(int x) {
    for(int i = x, j = 0; j < n; i++, j++)
        if(a[j] != b[i])
            return b[i] > a[j];
    return false;
}

void check() {
    for(int i = 0; i < n; i++)
        b[i] = b[n + i] = a[i];
    //move
    for(int i = 0; i < n; i++)
        if(b[i] == a[0] && judge(i))
            return ;
    //res
    for(int i = 0; i < 2 * n; i++)
        b[i] = -b[i];
    //opp and move
    for(int i = 0; i < n; i++)
        if(b[i] == a[0] && judge(i))
            return ;
    //swap and opp
    for(int i = 0; i < n; i++)
        swap(b[i],b[2 * n - i - 1]);
    //swap and opp and move
    for(int i = 0; i < n; i++)
        if(b[i] == a[0] && judge(i))
            return ;
    //opp
    for(int i = 0; i < 2 * n; i++)
        b[i] = -b[i];

    //swap and move
    for(int i = 0; i < n; i++)
        if(b[i] == a[0] && judge(i))
            return ;
    memcpy(s[ans++],a,sizeof(a));
}

void dfs(int cur, int Sum) {
    if(cur == n) {
        if(Sum == 0)
            check();
        return ;
    }

    if(abs(Sum) > ( (n - cur) * a[0]))
        return ;
    for(a[cur] = -a[0]; a[cur] < a[0]; a[cur]++) {
        if(a[cur - 1] == a[0] && a[cur] > a[1])
            return ;
        dfs(cur+1,Sum + a[cur]);
    }

    if(a[cur] == a[0] && a[cur - 1] <= a[1])
        dfs(cur+1,Sum + a[cur]);
}

int main() {
    int cas = 0;
    while(scanf("%d%d", &n, &k) != EOF && n) {
        ans = 1;
        for(a[0] = 1; a[0] <= k; a[0]++) 
            dfs(1,a[0]);

        if(cas++)
            printf("\n");
        printf("%d\n", ans);
        for(int i = 0; i < ans; i++)
            put(s[i]);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: