51nod - 1420 - 數袋鼠好有趣 - 貪心 - 二分
阿新 • • 發佈:2019-05-01
bool clas 最小 最大 http 網絡 pri 為什麽 一半
https://www.51nod.com/Challenge/Problem.html#!#problemId=1420
一開始亂搞了一發,每個袋鼠二分找最小的能放它的,然後二分的範圍從下一個開始保證不會把兩個小袋鼠裝在同一個裏面,還過了一半的數據……
然後才發現袋鼠並不能嵌套。想打vis標記大袋鼠跳過大袋鼠,然後樣例都過不了。
又想了半天網絡流,流個鬼鬼流。
看了一下別人的提示,貪心加二分。
好像我誤解了別人的貪心加二分,跑得比別人還快快。
明顯選的袋鼠一定是最小的那波,這樣最優。
然後二分選的袋鼠的數量,套在我第一次交的那個裏面,一發就過了,500ms,應該是正解的做法。
#include <bits/stdc++.h> using namespace std; typedef long long ll; int n; int a[500005]; int cpa[500005]; bool check(int m) { int be=m,en=n; for(int i=0; i<m; i++) { int res=lower_bound(a+be,a+en,2*a[i])-a; if(res==en) return false; else { be=res+1; } } return true; } int main() { while(~scanf("%d",&n)) { for(int i=0; i<n; i++) { scanf("%d",&a[i]); } sort(a,a+n); for(int i=0;i<m;i++){ } int ans=0; int l=0,r=n/2; while(1) { int m=(l+r)>>1; if(m==l){ if(check(r)){ ans=n-r; } else{ ans=n-l; } break; } if(check(m)){ l=m; } else{ r=m-1; } } printf("%d\n",ans); } }
然後看見一個更驚人的,從每個袋鼠開始選最大的能放進它的。好像沒什麽問題,這個貪心策略是對的。
2,4,5,8
從小的開始貪心,錯在假如2用了4,雖然減少了一個,但假如2用了5,4用了8,那就減少兩個。因為使用了4會影響4不能選8,所以不能這樣貪心。
但是從大的開始貪心就沒問題,例如8可以裝4,可以裝2,那裝4一定更好。(對個鬼鬼,假如有3呢?把4吃了2放哪裏?)。
其實這個策略的正確性應該在於先分成前後兩部分(至於為什麽要把奇數多出來的放在後部分,其實特判cnt不能超過n/2也可以,不然就有可能嵌套),前部分從後部分中選最合適的。這樣不會有嵌套。但居然也是500ms,感覺被騙了。
#include <bits/stdc++.h> using namespace std; typedef long long ll; int n; int a[500005]; int main() { while(~scanf("%d",&n)) { for(int i=0; i<n; i++) { scanf("%d",&a[i]); } sort(a,a+n,greater<int>()); int cnt=0; for(int i=(n+1)/2;i<n;i++){ if(a[cnt]>=2*a[i]) cnt++; } printf("%d\n",n-cnt); } }
或
#include <bits/stdc++.h> using namespace std; typedef long long ll; int n; int a[500005]; int main() { while(~scanf("%d",&n)) { for(int i=0; i<n; i++) { scanf("%d",&a[i]); } sort(a,a+n,greater<int>()); int cnt=0; for(int i=0;i<n;i++){ if(a[cnt]>=2*a[i]){ cnt++; if(cnt==n/2) break; } } printf("%d\n",n-cnt); } }
51nod - 1420 - 數袋鼠好有趣 - 貪心 - 二分