UVA - 269 Counting Patterns 构造

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开始枚举
给出学长的题解:
< http://blog.csdn.net/keshuai19940722/article/details/38016907 />

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值