国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Uva307 Sticks 【dfs+剪枝】【習題7-14】

2019-11-08 02:10:36
字體:
來源:轉載
供稿:網友

題目:Sticks

題意:起初有一些相等的木棍,然后被人砍成了n個木條。長度分別給出,現在需將n個木條組合拼成回原來的木棍,問原始木棍的最小可能長度?

思路:雖然知道用dfs,但沒想到怎么實現多個相等的判斷,然后參考了后做的,其實還是那些套路,就是變通不了。。。不過這個剪枝比較NB。。。

(1)枚舉:枚舉原始木棍長度,從總長度/i   i時n~1

(2)搜索:枚舉給出的數組,枚舉位置不是每次都從0開始,而成在遞歸中的pos參數,每次是從上一個的下一位開始的,遞歸中累加上木棍長度,當長度符合枚舉的原始木棍長度時,再繼續搜索,但是參數需要改變,pos從0開始,sum木棍長度也從0開始,當個數繼續+1,當個數與n相等時所有所有木條都組合拼成木棍了。

(3)剪枝:

①遞減排序,可以遞歸層數;

②枚舉原木棍長度應是總長度的倍數且大于最達的木條長度,其他的沒有必要搜索,因為根本達不到!

③當搜索時第i個木條時,第i個木條還未選(即放在還原標記數組的后面)時,如果后面的長度和i的相等,就沒有必要再枚舉,直接i++;(有點懵)

④當第i個木條沒有找到時,沒有必要再繼續尋找了,直接return剪枝。(還是有點懵!)

注意:以后判斷標記數組時用if(visit[i]) continue;  不能和有條件的判斷中加 !visit[i] 這樣時間會很慢!

參考:JeraKrs博客

代碼:

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int maxn = 100 + 5;bool cmp(int a,int b){return a > b;}int n,stick[maxn],visit[maxn];int ans,len;bool dfs(int steps,int pos,int sum){    if(steps == n) return true;//當到達第n個,說明所以木條都組合拼成了    for(int i = pos;i < n;i++){        if(visit[i]) continue;//關鍵,訪問過的跳過        if(sum + stick[i] < ans){            visit[i] = 1;            if(dfs(steps+1,i+1,sum + stick[i])) return true;            visit[i] = 0;            while(stick[i] == stick[i+1] && i+1 < n) i++;//剪枝:當i個數和第i+i數相等時,不需要再枚舉,因為依然小于ans        }        else if(sum + stick[i] == ans){            visit[i] = 1;            if(dfs(steps+1,0,0)) return true;//當達到組合值時,將組合木條長度和下標位置歸為0,繼續搜索,因為是幾個相等的木條,所以不是找到一個就行。。。            visit[i] = 0;            return false;        }        if(sum == 0) return false;//剪枝:當上面都沒有return時,程序會走到這一步,說明第i個木條沒有找到合適的組合,直接return     }        return false;}inline int solve(){    for(int i=n;i>=0;i--){//從大到小分        if(len % i == 0 && len / i >= stick[0]){//總長度的倍數且平分長度大于初始的最長木條才可進行組合            memset(visit,0,sizeof(visit));            ans = len / i;//當前組合長度            if(dfs(0,0,0)) return ans;        }    }    return -1;}int main(){    while(scanf("%d",&n)!=EOF && n){        len = 0;        for(int i=0;i<n;i++){            scanf("%d",&stick[i]);            len += stick[i];        }        sort(stick,stick+n,cmp);//遞減排序        PRintf("%d/n",solve());    }    return 0;}


上一篇:qt 問題

下一篇:二分搜索及測試函數

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 夏邑县| 晋江市| 郸城县| 茌平县| 绿春县| 普洱| 息烽县| 平度市| 广水市| 措勤县| 宁河县| 梅州市| 和龙市| 新闻| 石景山区| 舒城县| 南开区| 漯河市| 喀什市| 广水市| 乐都县| 东海县| 冷水江市| 峡江县| 大姚县| 宾川县| 米林县| 凤冈县| 恩施市| 杨浦区| 南通市| 汤原县| 鹤岗市| 顺平县| 麻栗坡县| 杭州市| 福清市| 岳阳县| 贡嘎县| 张家川| 镇安县|