1. 程式人生 > >codeforces_1075_C. The Tower is Going Home

codeforces_1075_C. The Tower is Going Home

http://codeforces.com/contest/1075/problem/C

題意:一個長寬均為1e9的棋盤,n個垂直障礙在x列無限長,m個水平障礙在第y行從第x1列到x2列。可以水平和垂直走。問從(1,1)走到(1e9,*)最少需要消除多少個障礙。

思路:只有遇到從1開始的水平障礙和一個垂直障礙相交時,棋子一定需要消除一個障礙,不從1開始的水平障礙都沒有意義。只考慮第一個垂直障礙左邊的情況,需要消除的障礙數時與第一個垂直障礙相交的水平障礙數。當選擇消掉第一個垂直障礙時,可能會因為這一次消除而造成之前若干個水平障礙的消除是無用的。並且水平障礙的順序可以任意,因而可以先升序排序,這樣可以降低複雜度。所以,應該優先考慮消除垂直障礙。遍歷從左開始消除垂直障礙的所有情況,取最小值。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;

    const int N=100005;
    const int M=1000000000;

    int main()
    {
        int n,m,cb[N],rb[N];
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i=1; i<=n; i++)
                scanf(
"%d",&cb[i]); cb[n+1]=M; int cntrb=0; for(int i=0; i<m; i++) { int x1,x2,y; scanf("%d%d%d",&x1,&x2,&y); if(x1==1) rb[cntrb++]=x2; } sort(cb,cb+n+1
); sort(rb,rb+cntrb); int ans=2*N; if((n==0&&m==0)||(cntrb==0)) ans=0; int tj=0; for(int i=1; i<=n+1; i++) { for(int j=tj; j<cntrb; j++) { if(rb[j]>=cb[i]) { int tmp=cntrb-j+i-1; ans=min(ans,tmp); tj=j; break; } if(j==cntrb-1) ans=min(ans,i-1); } } printf("%d\n",ans); } return 0; }