BZOJ 1110: [POI2007]砝码Odw( 贪心 )
ORZjcvb...
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 100009; 6 7 int N, M, item[maxn], V[maxn]; 8 vector<int> o, cnt, Div; 9 10 int main() { 11 12 cin >> N >> M; 13 for(int i = 0; i < N; i++) 14 scanf("%d", V + i); 15 for(int i = 0; i < M; i++) 16 scanf("%d", item + i); 17 18 sort(item, item + M); 19 o.push_back(item[0]); cnt.push_back(1); 20 for(int i = 1; i < M; i++) 21 if(item[i] == item[i - 1]) cnt[cnt.size() - 1]++; 22 else { 23 o.push_back(item[i]); 24 cnt.push_back(1); 25 } 26 27 int S = o.size(); 28 Div.resize(S); 29 for(int i = 0; i < N; i++) { 30 for(int j = S - 1; ~j; j--) { 31 int t = V[i] / o[j]; 32 Div[j] += t; 33 V[i] -= t * o[j]; 34 } 35 } 36 37 int ans = 0; 38 for(int i = 0; i < S; i++) { 39 if(cnt[i] > Div[i]) { 40 for(int j = i + 1; j < S && Div[i] < cnt[i]; j++) if(Div[j]) { 41 int c = 1; 42 for(; o[j] / o[i] * c < cnt[i] - Div[i]; c++) 43 if(c == Div[j]) break; 44 Div[j] -= c; Div[i] += o[j] / o[i] * c; 45 } 46 ans += min(Div[i], cnt[i]); 47 if(Div[i] < cnt[i]) break; 48 } else 49 ans += cnt[i]; 50 } 51 printf("%d\n", ans); 52 53 return 0; 54 }
1110: [POI2007]砝码Odw
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 366 Solved: 202
[Submit][Status][Discuss]
Description
在byteotian公司搬家的时候,他们发现他们的大量的精密砝码的搬运是一件恼人的工作。公司有一些固定容量的容器可以装这些砝码。他们想装尽量多的砝码以便搬运,并且丢弃剩下的砝码。每个容器可以装的砝码数量有限制,但是他们能够装的总重量不能超过每个容器的限制。一个容器也可以不装任何东西。任何两个砝码都有一个特征,他们的中总有一个的重量是另外一个的整数倍,当然他们也可能相等。
Input
输入文件的第一行包含两个数n和m。表示容器的数量以及砝码的数量。(1<=n, m<=100000) 第二行包含n个整数wi,表示每个容器能够装的最大质量。(1<=wi<=1000000000) 第三行包含m个整数mj,表示每个砝码的质量。(1<=mj<=1000000000)
Output
输出文件要求仅包含一个数,为能够装进容器的最多的砝码数量。
Sample Input
2 4
13 9
4 12 2 4
13 9
4 12 2 4
Sample Output
3