HDOJ-1557(枚举或搜索)

来源:互联网 发布:微盘交易源码 阴极铜 编辑:程序博客网 时间:2024/06/07 04:48

题目中每个团体加入或不加入联盟一共有2^20种可能性,数据规模很小,直接枚举即可:


#include <stdio.h>int main(){    int test, i, k, limit, mask, sum;    int N, arr[20], cnt[20], threshold;    scanf("%d", &test);    while(test--){        threshold = 0;        scanf("%d", &N);        for(i = 0; i < N; ++i){            scanf("%d", &arr[i]);            threshold += arr[i];            cnt[i] = 0;        }        threshold = threshold / 2 + 1;        for(k = 1, limit = 1 << N; k < limit; ++k){            sum = 0;            for(i = 0; (mask = 1 << i) <= k; ++i){                if(k & mask) sum += arr[i];            }            if(sum < threshold) continue;            for(i = 0; (mask = 1 << i) <= k; ++i){                if((k & mask) && sum - arr[i] < threshold) ++cnt[i];            }        }        printf("%d", cnt[0]);        for(i = 1; i < N; ++i) printf(" %d", cnt[i]);        puts("");    }    return 0;}
用DFS代替手动枚举还可以写成:

#include <stdio.h>int N, arr[20], cnt[20], threshold;int stack[20], size;void dfs(int i, int sum){    if(i < 0){        if(sum >= threshold){            int k = 0;            for(; k < size; ++k){                if(sum - arr[stack[k]] < threshold) ++cnt[stack[k]];            }        }        return;    }    dfs(i - 1, sum);    stack[size++] = i;    dfs(i - 1, sum + arr[i]);    --size;}int main(){    int test, i;    scanf("%d", &test);    while(test--){        threshold = 0;        scanf("%d", &N);        for(i = 0; i < N; ++i){            scanf("%d", &arr[i]);            threshold += arr[i];            cnt[i] = 0;        }        threshold = threshold / 2 + 1;        size = 0;        dfs(N-1, 0);        printf("%d", cnt[0]);        for(i = 1; i < N; ++i) printf(" %d", cnt[i]);        puts("");    }    return 0;}
上面不加剪枝的DFS和枚举实际上都是遍历所有的可能性,但从结果上来看,DFS还是快一些,毕竟枚举的时候每次都还要扫描2遍全部团体是否加入,而DFS时已经将这一信息记录下来了


0 0
原创粉丝点击