日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

回溯算法之幸运的袋子

發(fā)布時(shí)間:2025/3/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 回溯算法之幸运的袋子 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

解法框架

【README】回溯算法基本框架

幸運(yùn)的袋子(點(diǎn)擊跳轉(zhuǎn))

這道題基本也是回溯,題解中有一部分提到了dfs,其實(shí)dfs本質(zhì)也是回溯算法。這道題有點(diǎn)特別,除了考察算法外,還輕微涉及一點(diǎn)數(shù)學(xué)知識,其實(shí)也可以說是規(guī)律吧。此題本質(zhì)就是在集合中找到符合條件的子集,這條件就是子集中所有數(shù)字的和大于所有數(shù)字的積

規(guī)律如下

  • 數(shù)論中:對于兩個(gè)任意的正整數(shù)a和b,如果要滿足a+b<ab,則必須要有一個(gè)數(shù)為1
  • 我們將所有的球排好序后,假設(shè)a1,a2,a3不滿足條件,那么也就是sum<=multi,如果要選擇一個(gè)數(shù)b使得sum+b>multi*b,那么b一定為1。但是如果選擇的b>1,那么一定不滿足條件,同時(shí)排在b后面的數(shù)組更不可能滿足條件
  • 如果有連續(xù)的1存在,且當(dāng)前位置不滿足條件,但是該位置的數(shù)字為1,那么應(yīng)該繼續(xù)向后找尋,因?yàn)橹灰?就能增大sum,而不會使multi變大
  • 對于重復(fù)的數(shù)字只算一次,也就是咋們在回溯算法中說到過的在選擇列表中選擇正確的選項(xiàng)
  • 首先,這道題要完全自己輸入和輸出,先打起框架。咋們的選擇列表,也就是所有球的編號,依次存放在一個(gè)vector中,接著將球按照編號從小到大的排序

    #include <iostream> #include <vector> #include <algorithm> using namespace std;int main() {int n;//接受幾個(gè)球cin>>n;vector<int> ball;for(int i=0;i<n;i++){int temp;cin>>temp;ball.push_back((temp));}sort(ball.begin(),ball.end());//排序}

    選擇列表有了,下一個(gè)就是路徑,這個(gè)路徑非常簡單,只需要一個(gè)整型ret即可,因?yàn)楫?dāng)sum>multi的時(shí)候,這表明現(xiàn)在就已經(jīng)可以作為一個(gè)幸運(yùn)的袋子了,所以ret增加。 所以將ret設(shè)置為全局變量。

    對于遞歸函數(shù),第一個(gè)參數(shù)一定是選擇列表,第二個(gè)參數(shù)是球的個(gè)數(shù),第三個(gè)參數(shù)要設(shè)置為一個(gè)pos,因?yàn)檫f歸函數(shù)進(jìn)行for循環(huán)時(shí)一定要一個(gè)正確的起始位置,for循環(huán)每次就從i=pos的位置,遞歸時(shí)這個(gè)球加入了,我們就pos=i+1,表明選擇下一個(gè)球。剩下兩個(gè)參數(shù)分別為sum和multi用于計(jì)算判斷

    int ret=0;//幸運(yùn)的袋子個(gè)數(shù) void back(vector<int>& ball,int n,int pos,int sum,int multi) {for(int i=pos;i<n;i++){sum+=ball[i];//和multi*=ball[i];//乘積if(sum>multi)//ball[i]這個(gè)球加入后符合幸運(yùn)袋子{ret+=1;back(ball,n,i+1,sum,multi);//繼續(xù)回溯,下一個(gè)位置}else if(ball[i]==1)//如果不滿足條件,但是這一位是1,是還有機(jī)會的,所以遞歸就可以了{back(ball,n,i+1,sum,multi);}else{break;//不滿足直接退出}sum-=ball[i];//撤銷選擇multi/=ball[i];//撤銷選擇while(i<n-1 && ball[i]==ball[i+1])//連續(xù)的只選擇1次{++i;}}}

    需要注意的是去重要寫在后面,不要一上來就去重

    最后完善即可,注意multi在傳入時(shí)要傳入1,不要傳入0

    #include <iostream> #include <vector> #include <algorithm> using namespace std;int ret=0;//幸運(yùn)的袋子個(gè)數(shù) void back(vector<int>& ball,int n,int pos,int sum,int multi) {for(int i=pos;i<n;i++){sum+=ball[i];//和multi*=ball[i];//乘積if(sum>multi)//ball[i]這個(gè)球加入后符合幸運(yùn)袋子{ret+=1;back(ball,n,i+1,sum,multi);//繼續(xù)回溯,下一個(gè)位置}else if(ball[i]==1)//如果不滿足條件,但是這一位是1,是還有機(jī)會的,所以遞歸就可以了{back(ball,n,i+1,sum,multi);}else{break;//不滿足直接退出}sum-=ball[i];//撤銷選擇multi/=ball[i];//撤銷選擇while(i<n-1 && ball[i]==ball[i+1])//連續(xù)的只選擇1次{++i;}} }int main() {int n;//接受幾個(gè)球cin>>n;vector<int> ball;for(int i=0;i<n;i++){int temp;cin>>temp;ball.push_back((temp));}sort(ball.begin(),ball.end());//排序back(ball,n,0,0,1);cout<<ret<<endl;return 0;}

    總結(jié)

    以上是生活随笔為你收集整理的回溯算法之幸运的袋子的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。