二分/模擬-51Nod 1279-扔盤子
阿新 • • 發佈:2018-11-19
題目連結:1279扔盤子
題目大意:
盤子有幾種命運:1、掉到井底。2、被卡住。3、落到別的盤子上方
思路:
如果簡單的暴力會超時,對井的每一層可做優化。
如果上一層比下一層窄,那麼盤子肯定在上一層被卡,所以不妨把下一層的寬度也設為上一層的寬度,以此,井由上至下會變成一個非遞增序列,便於查詢。
二分解法:
將井“倒過來”,變成一個非遞減序列,設定一個下界,查詢盤子所能落到的最底位置,更新下界,直到盤子不能入井。
#include<iostream> #include<algorithm> using namespace std; #define min(a,b) (a<b?a:b) #define INF 1<<30 #define MAX_SIZE 50005 int Depth[MAX_SIZE]; int N,M; int Up_Bound; int Binary_Search(int Width) { int l=Up_Bound,r=N; while(l<=r) { int mid=(l+r)/2; if(Width<=Depth[mid]) r=mid-1; else l=mid+1; } return l<=N? Up_Bound=l+1 : 0; //l>N放不下,返回0,否則返回新的下界 } int main() { while(cin>>N>>M) { Up_Bound=0; int Res=0; int StopFlag=0; int Width; Depth[0]=INF; for(int i=1;i<=N;i++) { cin>>Depth[i]; Depth[i]=min(Depth[i],Depth[i-1]); //預處理,取上下層窄 } sort(Depth+1,Depth+N+1);//倒序 for(int i=1;i<=M;i++) { cin>>Width; if(!Binary_Search(Width))//查詢盤子能到最底的位置 StopFlag=1; if(StopFlag) //井放不下,只輸入不做處理 continue; Res++; } cout<<Res<<endl; } return 0; }
純暴力:
#include<stdio.h> #define MAX_SIZE 50005 int Depth[MAX_SIZE]; int NowMaxDepth; int N,M,Plate; int cnt=0; int main() { scanf("%d%d",&N,&M); NowMaxDepth=N; for(int i=1;i<=N;i++) scanf("%d",&Depth[i]); for(int i=1;i<=M;i++) { scanf("%d",&Plate); if(NowMaxDepth<=0) continue; int j; for(j=1;j<=NowMaxDepth;j++) if(Plate>Depth[j]) break; if(j>NowMaxDepth) //每一層寬度都大於盤,落到當前的底,-1 NowMaxDepth-=1; else //盤子被卡住,-2 NowMaxDepth=j-2; if(NowMaxDepth!=-1) cnt++; //cout<<"Now: "<<NowMaxDepth<<endl; } printf("%d\n",cnt); }