【POJ1011 Sticks】解題報告+思路+代碼

來源:互聯網
上載者:User
#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#include <iostream>//#define INPUTusing namespace std;/**    Problem : poj1011 - Sticks    Begin Time : 13:00 p.m. 15th/mar/2012    End Time : 15:10 p.m. 15th/mar/2012    【看別人的報告過的】    Reference : 程式設計線上導引 , PKU出版。    Knowledge : DFS,回溯法,重疊子問題用遞迴解,剪枝思想    Thought:    我們用遞迴的思想解決這個問題,設某一個函數    f(totalSticks,leftNum,leftLenth,totalLenth),    其中    totalSticks代表總共有多少根棍子。    leftNum代表剩了多少根棍子。    leftLenth代表拼的當前棍子還有多長才能拼成totalLenth。    totalLenth代表要拼出來的長度。    bool f(totalSticks,leftNum,leftLenth,totalLenth)    {        int i;        if( leftLenth == 0 && leftNum == 0 ) return true;        if( leftLenth == 0 ) leftLenth = totalLenth; //拼完一個拼下一個        for( i = 0 ; i < totalSticks ; i++)        {          if(used[i]) continue; ///這根棍子被用過          if(sticks[i] > leftLenth) continue; ///當前選擇的棍子太長了          if(totalSticks(totalSticks,leftNum-1,leftLenth-sticks[i],totalLenth) return true;          used[i] = false;回溯        ////下方這個剪枝十分重要!          IF( leftlenth == nums[i] || leftlenth == totallenth ) BREAK;        ////    解釋如下:        ///// ① leftlenth = nums[i] : nums[i]是所拼長度的最後一個棍子        /////  這種情況下,把nums[i]拼出來一個目標長度之後還能運行到剪枝語句        /////  就證明拼完了nums[i]剩下的棍子拼不出來目標長度        /////  如果不break,繼續執行        /////  設nums[i]可以被其他的棍子替代,並且nums[i]可以在其他情況拼出來目標長度        /////  那麼把這兩種情況互換一下,即nums[i]拼上,然後用這些替代nums[i]的小木棍去拼其他情況        /////  這樣,nums[i]拼完之後就可以拼出來目標長度了        /////  而這跟既成事實是矛盾的,所以要break;        ///// ② leftlenth = totallenth,這就證明nums[i]是第一個棍子        /////    第一個都拼不出來,那麼nums[i]就註定無論在任何情況下都拼不出目標長度,所以break;        }        return false;    }    我們將所有stick的長度讀入數組nums中,並按照長度降序排列。    for( len = nums[0]; len <= sum; len++)    {        if(f(totalSticks,totalSticks,len,len))          printf("%d\n",len);    }    len的取值範圍是nums最大值到nums的和。    教訓:        對於重疊子問題要使用遞迴結構,而這道題,重疊子問題我都想到了        但是沒想到使用遞迴結構,這道題的收穫就是        “拼出目標長度”的遞迴寫法        自己錯的地方也在《導引》中提到了,是第一個錯誤點。        這道題還是很牛逼的,要多看看*/const int c0de4fun = 100;int nums[c0de4fun];int used[c0de4fun];int comp(const void *a,const void *b){    return (*(int*)b - *(int*)a);}bool solve(int tot_num,int left_num,int left_len,int tot_len){    int i;    if ( left_num == 0 && left_len == 0 ) return true;    if ( left_len == 0 ) left_len = tot_len;    for( i = 0 ; i < tot_num ; i++ )    {        if( used[i] ) continue;        if( nums[i] > left_len ) continue;        used[i] = true;        if( solve(tot_num,left_num-1,left_len-nums[i],tot_len) ) return true;        used[i] = false;        if( left_len == tot_len || nums[i] == left_len ) break;    }    return false;}int main(){#ifdef INPUT    freopen("b:\\acm\\poj1011\\input.txt","r",stdin);#endif    int n,i,len,sum;    while ( scanf("%d",&n) != EOF )    {        if( n == 0 ) break;        memset(nums,0,sizeof(nums));        memset(used,0,sizeof(used));        sum = len = 0;        for (i = 0 ; i < n ; i++)        {            scanf("%d",&nums[i]);            sum += nums[i];        }        qsort(nums,i,sizeof(int),comp);        for(len = nums[0]; len <= sum ; len++)        {            if ( sum % len != 0) continue;            if(solve(i,i,len,len))                printf("%d\n",len);        }    }    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.