權利指數(hdu 1557)


此題鏈接單擊這里

=================

此題只要枚舉出所有子集即可AC~~~~~好吧,關鍵就是怎么枚舉子集。。。
做此題之前根本不知道怎么枚舉子集,把紫書(劉汝佳著)子集生成一節看幾遍,最后用二進法做此題(就看懂了這個~~~)。

二進制法枚舉子集:
n個數有2^n個子集,每個子集對應一個二進數,每位二進制對應一個數。二進制的位權為0表示子集不包含那個數,二進制的位權為1表示子集包含那個數。

案例
2
1
10
7
5 7 4 8 6 7 5
取n=7

<2^7=128 二進制 子集
0 0 0
1 1 5
2 10 7
3 11 5,7
57 111001 5,8,6,7
127 111111 5,7,4,8,6,7,5
//關鍵代碼

void funt(int n,int s)
{
    for(int i=0;i<n;i++)
        if(s&(1<<i)) //n的子集共有2^n個,若s=13(1101),剛i=0,2,3時輸出
                     //13&(1<<0)->13&1  ==1
                     //13&(1<<2)->13&4  ==1
                     //13&(1<<3)->13&8  ==1
                     // 反例13&(1<<4)->13&16 ==0
           printf("%d",i);
        printf("\n");

}
int main()
{
    int n=7;
    for(int i=0;i<(1<<n);i++)//i<(i<<n) -> i<128
        funt(n,i);
}

附題目代碼

#include <iostream>
#include <cstring>
using namespace std;
int k;
int a[20];
int b[20];
int c[20];
long sum;
int ave;
void funt(int n, int s)
{
    sum = 0;
    memset(b, 0, sizeof(b));
    for (int i = 0; i < n; i++)
        if (s&(1 << i))
        {
            sum += a[i];
            b[i] = 1;
        }
    if (sum >ave)
        for (int i = 0; i < n; i++)
            if (b[i] == 1 && (sum - a[i])<=ave)
                c[i]++;
}

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        memset(c, 0, sizeof(c));
        int n;
        cin >> n;
        ave = 0;
        for (int i = 0; i < n; i++)
        {
            cin >> a[i];
            ave += a[i];
        }
        ave = ave / 2;
  // if (ave % 2 != 0)
  // ave++;
        for (int i = 0; i < (1 << n); i++)
            funt(n, i);
        int loge=1;
        for (int i = 0; i < n; i++)
            if(loge)
               {
                   cout << c[i];
                   loge=0;
               }
            else
                cout<<' '<<c[i];
        cout<<endl;
    }
    return 0;
}

有問題聯系企鵝791267032
郵箱地址….wutanrong@Hotmail.com


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com