NYOJ 還是01揹包(列舉 二分)

2021-07-11 13:09:43 字數 1552 閱讀 9088

還是01揹包

時間限制:10000 ms | 記憶體限制:228000 kb

難度:5

描述有n個重量和價值分別為 wi 和 vi 的物品,從這些物品中挑選總重量不超過w的物品,求所有挑選方案中價值總和的最大值。

輸入多組測試資料。

每組測試資料第一行輸入n 和 w ,接下來有n行,每行輸入兩個數,代表第i個物品的wi 和 vi。

1 <= n <=40

1 <= wi <= 10^15

1 <= vi <= 10^15

1 <= w <= 10^15

輸出每組資料輸出一行,代表挑選方案中價值總和的最大值。

樣例輸入

4 52 3

1 23 4

2 2樣例輸出

這題寫了好久,調了好久,心塞。

這題解題思路是這樣的,首先看一下vi, wi, w便知太大了,所有的揹包動態規劃方程都顯得無能為力了。看一下n<=40, 沒辦法了只能從這邊入手了。怎麼做呢?沒想到其他的,直接列舉就是了。但是列舉也是需要技巧的,40個得有2^40的量,會崩潰的額,也就是說時間複雜度為o(2^n);接下來就是要做優化工作了。其實以前做題的時候也做過類似思想的題,就是把n個物品分成兩半,每一半就剩下n/2個,這樣複雜度降的很多。用乙個整數來表示方案,用到位運算來表示,例如2的二進位制位11,這表示第乙個和第二個都拿,又如1的二進位制數為01, 這表示第乙個拿,第二個物品不拿,這樣表示簡潔簡單且速度快。設前半部分某種方案是得到的重量為w1, 價值為v1,這在第二部分中w2,v2必定有w2+w1<=w; 所以就列舉第一部分,再去第二部分中找w2<=w-w1時價值的最大值。然後第二部分開始時就應該按wi,,vi的字典序排序,因為如果有wivj那麼i方案一定優於j方案。所以在第二部分中排完序之後會剔除掉某些方案。然後既然排好序就得按二分思想來查詢。

ac**:

# include # include using namespace std;

typedef long long int ll;

struct goods;

goods s1[30], s2[30];//輸入資料

goods change_s2[(1<<20)+10];//轉化為w與v的和

int compare(goods a, goods b)

change_s2[cur2].w=sum_w;

change_s2[cur2].v=sum_v;

cur2++;

} //排序

sort(change_s2+1, change_s2+cur2, compare);

now_v=-1;_cur2=1;

//剔除掉一些不符合的方案

for(i=1; i<=cur2-1; i++)

} ans=0;

//列舉第一部分的所有情況並到第二部分二分搜尋

for(num_set=0; num_set<=(1<>1;

}if(sum_w<=w)

}else}}

} printf("%lld\n", ans);

} return 0;

}

NYOJ又見01揹包

描述 有n個重量和價值分別為wi 和 vi 的 物品,從這些物品中選擇總重量不超過 w 的物品,求所有挑選方案中物品價值總和的最大值。1 n 100 1 wi 10 7 1 vi 100 1 w 10 9 輸入 多組測試資料。每組測試資料第一行輸入,n 和 w 接下來有n行,每行輸入兩個數,代表第i...

nyoj 860 又見01揹包(01 揹包)

又見01揹包 時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 有n個重量和價值分別為wi 和 vi 的 物品,從這些物品中選擇總重量不超過 w 的物品,求所有挑選方案中物品價值總和的最大值。1 n 100 1 wi 10 7 1 vi 100 1 w 10 9 輸入 多組測試...

SPOJ RENT 01揹包的活用 二分

這個題目給定n航班的發出時間和結束時間以及價值,要求不衝突時間的最大價值 第一時間想到經典的n方dp,即對航班按發出時間排一下序之後每個i對前面的都掃一遍 時間過不了n有10萬,只能想優化了,一開始想了個用樹狀陣列記錄每次加入某個航班之後 後面的所有在結束時間後的區間全部可以加乙個最大值,但是首先時...