1. 程式人生 > 實用技巧 >NOIP2006提高組第二題-金明的預算方案

NOIP2006提高組第二題-金明的預算方案

題意:揹包問題,每個物品有價值和所謂的重要度,以及可以是其他物品的附件,只有購買了主件才能購買附件,.求有n元買m件以內的物品的最大價值和重要度乘積的和.其中一個主件的附件數比較少,最多隻有2個附件.

分析:資料範圍比較小,最多隻有2個附件直接分組揹包,m件是典型二維費用揹包,注意列舉順序是先分組再列舉二個維度最後再列舉組內的物品.

附上自己亂寫的常數大的一批的醜b程式碼:

  1 #pragma GCC optimize(2)
  2 #include <cstdio>
  3 #include <iostream>
  4 #include <cstring>
  5
#include <cstdlib> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <deque> 11 #include <list> 12 #include <climits> 13 #include <bitset> 14 #include <fstream> 15 #include <algorithm> 16
#include <functional> 17 #include <stack> 18 #include <string> 19 #include <cmath> 20 #define fi first 21 #define se second 22 #define re register 23 #define ls i << 1 24 #define rs i << 1 | 1 25 #define pb push_back 26 #define mp make_pair 27 #define pii pair<int,int> 28
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 29 #define mod 1000000007 30 31 //#define int long long 32 33 using namespace std; 34 const double eps = 1e-8; 35 const int inf = 0x3f3f3f3f; 36 const long long INF = 0x3f3f3f3f3f3f3f3f; 37 const double pi = acos(-1.0); 38 39 inline int rd(){ 40 re int res = 0,flag = 0;char ch; 41 if ((ch = getchar()) == '-')flag = 1; 42 else if(ch >= '0' && ch <= '9')res = ch - '0'; 43 while ((ch = getchar()) >= '0' && ch <= '9')res = (res<<1) + (res<<3) + (ch - '0'); 44 return flag ? -res : res; 45 } 46 47 void out(int a) { 48 if (a < 0) { 49 putchar('-');a = -a; 50 } 51 if (a >= 10) out(a / 10); 52 putchar(a % 10 + '0'); 53 } 54 55 const int maxn = 4e4+10; 56 const int maxm = 100; 57 int n, m; 58 int f[maxn][maxm]; 59 60 struct thing{ 61 int val, v, m, id, q; 62 bool friend operator<(const thing &a, const thing &b) { 63 return a.q < b.q; 64 } 65 }; 66 67 vector<thing> goods,e[maxm]; 68 69 //二維費用: 1.價值 2.數量 70 //求最大收益: 價值 * 重要度 71 72 //signed main(){ 73 int main() { 74 n = rd(), m = rd(); 75 for (int i = 1; i <= m; i++) { 76 int v = rd(), p = rd(), q = rd(); 77 goods.pb({v*p, v, 1, i, q}); 78 } 79 sort(goods.begin(), goods.end()); 80 for (int i = 0; i < goods.size(); i++) { 81 if (goods[i].q == 0) e[goods[i].id].pb({goods[i].val, goods[i].v, 1}); 82 else { 83 int now = goods[i].q; 84 int len = e[now].size(); 85 for (int j = 0; j < len; j++) { 86 e[now].pb({e[now][j].val + goods[i].val, e[now][j].v + goods[i].v, e[now][j].m + 1}); 87 } 88 } 89 } 90 for (int i = 1; i <= m; i++) {//分組 91 if (e[i].size() == 0) continue; 92 for (int k = n; k >= 0; k--) {//第一維費用 93 for (int j = m; j >= 0; j--) {//第二維費用 94 for (int s = 0; s < e[i].size(); s++) //列舉組內物品 95 if (k >= e[i][s].v && j >= e[i][s].m) 96 f[k][j] = max(f[k][j], f[k-e[i][s].v][j-e[i][s].m] + e[i][s].val); 97 } 98 } 99 } 100 out(f[n][m]); 101 return 0; 102 }