16122020 鐘順源
將n個體積分別為wi貨櫃放置在容量分別為c1,c2的輪船中,問是否能有個合理放置的方案,若有,則輸出字典序最大的方案。題目可以轉換為有n個元素,對於某個元素,有取或不取兩個操作,取的貨櫃總體積不超過c1,不取的貨櫃總體積不超過c2,取或不取的問題可以dp做,爆搜當然也可以,但既然學到的搜尋,就爆搜+減枝。
因為要記錄最佳的方案情況,而更新一次最佳方案需要o(n
)o(n)
o(n)
的複雜度搜尋每一種方案需要o(2
n)
o(2^n)
o(2n
),所以總的複雜度是o(n
×2n)
o(n×2^n)
o(n×2n
)的複雜度,那如何將複雜度降為o(2
n)
o(2^n)
o(2n)?
做加法不做乘法。
先找出第一艘船能裝的滿足條件的最多貨物,之後在按先搜1再搜0的順序搜尋第乙個滿足條件的組合,因為是按1,0的順序搜尋的,所以第乙個滿足條件的方案一定是字典序最大的。
簡單來說就是 兩次dfs。
#includeusing namespace std;
const int n=30;
int a[n],b[n];
int bestw=0;//
int n; int c1,c2;
int all;
int fac[n],pre[n];
int cnt=0;
setans;
void dfs1(int pos,int sum)
if(sum + fac[pos] < bestw) return ;
if(sum + a[pos] <= c1)
dfs1(pos+1,sum+a[pos]);
if(pre[pos] - sum <= c2)
dfs1(pos+1,sum);
}void dfs2(int pos,int sum,string xx)
if(sum + fac[pos] < bestw) return ;
if(sum + a[pos] <= c1)
dfs2(pos+1,sum+a[pos],xx+'1');
if(ans.size()) return ;
if(pre[pos] - sum <= c2)
dfs2(pos+1,sum,xx+'0');
}int main()
fac[n+1] = 0;
for(int i=n;i>=1;i--) fac[i] = fac[i+1] + a[i];
scanf("%d%d",&c1,&c2);
printf("case %d\n",++cas);
bestw=-1;
dfs1(1,0);
dfs2(1,0,"");
if(bestw==-1)
cout《這次實驗還是蠻有意思的,之前一直沒有考慮到更新的答案的開銷如何消除,但沒想到只要先處理出答案,在去搜字典序最大的路徑就可以了,兩個dfs的複雜度都是o(2
n)
o(2^n)
o(2n
),所以最後的總的複雜度也是o(2
n)
o(2^n)
o(2n)。
裝載問題 回溯演算法
題目描述 有一批共n個貨櫃要裝上2艘載重量分別為c1和c2的輪船,其中貨櫃i的重量為wi。裝載問題要求確定,是否有乙個合理的裝載方案可將這n個貨櫃裝上這2艘輪船。如果有,找出一種裝載方案。題目出自 計算機演算法設計與分析 第三版 王曉東 這是乙個典型的回溯演算法問題。如下 template clas...
演算法作業(裝載問題)
有n個貨櫃要裝上2艘載重量分別為c1和c2的輪船,其中第i個貨櫃的重量為wi,要求確定是否有乙個合理的裝載方案可將這個貨櫃裝上這2艘輪船。如果有,找出一種裝載方案。注意,在滿足的條件下才可能將這個貨櫃裝上這2艘輪船。輸入有若干組測試資料 不超過20組 每組測試資料有3行 其第1行上是貨櫃個數n,n ...
回溯演算法 裝載問題
給定n個貨櫃要裝上一艘載重量為c的輪船,其中貨櫃i的重量為wi。貨櫃裝載問題要求確定在不超過輪船載重量的前提下,將盡可能多的貨櫃裝上輪船 貪心演算法中的裝載問題討論的是裝載件數 本題討論的是最大裝載重量。由於貨櫃問題是從n個貨櫃裡選擇一部分貨櫃,假設解向量為x x1,x2,xn 其中xi xi 1表...