資訊學 (電腦) 奧林匹克訓練題(中級部分)

來源:互聯網
上載者:User
題目請前往以下連結查看,由於該練習題在網上被大量轉載,原出處似乎很難找到,從中挑選到一時間較早的,如下:
資訊學 (電腦) 奧林匹克訓練題(中級部分)

網上能搜到一些答案,由於時間限制,本人暫不一一列出。

今天做了第30道,覺得有點難度。

某機要部門安裝了電子鎖。M個工作人員每人發一張磁卡,卡上有開鎖的密碼特徵。

 

為了確保安全,規定至少要有N個人同時使用各自的磁卡才能將鎖開啟。問電子鎖上至 少要有多少種特徵?每個人的磁卡上至少要有多少特徵?如果特徵的編號以小寫英文字母表示,將每個人的磁卡的特徵編號列印出來,要求輸出的電子鎖的總特徵數最少。

 

設 3<=M<=7, 1<=N<=4, M與N由鍵盤輸入,工作人員編號用1#,2#,...表示.

相關分析可以看2_組合計數劉汝佳黑書課件

上面的講解很清晰 (百度文庫 0積分下載)

我的解法如下:(寫了一上午,頭暈死了,還沒最佳化過,可能有部分邏輯不清的地方,暫時輸出的結果是對的,Code::Blocks下調試通過)

#include <stdio.h>char table[35][7] = {0};char pers[7][35] = {0};int M;int N;int factorial(int integer){    int ret = 1;    if (!integer)    {        return 1;    }    while (integer)    {        ret *= integer--;    }    return ret;}int Combination(int m, int n){    return factorial(m)/(factorial(n)*factorial(m-n));}void init_combination(int n){    int i;    for (i = 0; i<n; i++)    {    table[0][i] = 1;    }}void next_combination(int num, int n){    int i;    int len = 0;    int stop = 0;    for (i = 0; i < num; i++)    {    if (table[n][i] == 0)//當前為0    {        if (stop == 0) len++;    }    else if (len > 0)//當前為1 len>0    {        if (stop == 0)        {           if(table[n][i + 1] == 1)//下一項為1                {                    table[n + 1][i - len] = 1;                    table[n + 1][i] = 0;                }                else//下一項為0                {                    table[n + 1][i] = 0;                    table[n + 1][i + 1] = 1;                    stop = 1;                }        }        else        {            table[n + 1][i] = 1;        }    }    else//當前為1 len=0    {        if(table[n][i + 1] == 0 && stop == 0)//下一項為0        {            table[n + 1][i] = 0;            table[n + 1][i + 1] = 1;            stop = 1;        }        else//下一項為1        {            table[n + 1][i] = 1;        }    }    }}void set_person_keys(){    int i, j;    for (i = 0; i < Combination(M,M - N + 1); i++)    {    for (j = 0; j < M; j++)    {    if (table[i][j] == 1)    {    pers[j][i]='A' + i;    }    }    }}int main(void){    int i, j;    int key,person;    printf("某機要部門安裝了電子鎖。M個工作人員每人發一張磁卡,卡上有開鎖的密碼特徵。\n請輸入總人數M(3<=M<=7):\n");    scanf("%d", &M);    printf("為了確保安全,規定至少要有N個人同時使用各自的磁卡才能將鎖開啟。\n請輸入N的值(1<=N<=4):\n");    scanf("%d", &N);    key = Combination(M,N-1);    printf("電子鎖上至少要有%d種特徵\n", key);    person = Combination(M-1, N-1);    printf("每個人的磁卡上至少要有%d種特徵\n", person);    init_combination(M - N + 1);    for (i = 0; i < Combination(M,M - N + 1); i++)    {        /*清除下面5行的“//”可顯示從M人中挑選(M-N+1)人的所有組合(用二進位位表示)*///    for (j = 0; j < M; j++)//    {//    printf("%d", table[i][j]);//    }//    printf("\n");    next_combination(M, i);    }    set_person_keys();    for (i = 0; i < M; i++)    {        printf("%d# ", i+1);    for (j = 0; j < Combination(M,M - N + 1); j++)    {    printf("%c",pers[i][j]);    }    printf("\n");    }    printf("上面每一列字母的個數都是%d,空餘數為%d,對於每一列來說任選%d行都可以選擇到一個字母\n",M-N+1,N-1,N);    return 0;}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.