UVa 11134 貪心

【題目鏈接】
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34086

【解題報告】
題目大意:
在N*N的棋盤裏放N個車,使彼此不互相攻擊(即不同行,不同列),每個車可以放在一個子矩陣裏(給出矩陣左上角,右下角的座標),請給出任意一種放車的方案,如果不存在,輸出”IMPOSSIBLE”。
這題的貪心解法還是很值得認真體會的。
首先,行和列不相互影響,可以分開考慮,這點應該大家都知道,並沒有什麼難度,那麼問題轉化爲:

給出一條線上n個位置,把n個不同的車放進去,每個車有一個擺放區間,求一個方案。

這題我們很容易這樣想:每個車的擺放位置對應一條線段,那麼我們把n條線段從小到大排個序,然後從左到右依次擺放。怎麼排序呢?
左端點優先?
那麼(1,3),(1,3),(2,2)這種情況就會輸出impossible,問題在哪裏呢?
原因在於,我們在前面選了一條右端點靠後的,也就是說可以放在當前位置,也可以放在更後面的位置的線段,那麼可能後面的線段就沒有位置可以放了。
所以我們需要修正一下算法:每次挑一條對右邊影響最小的線段,先把他的位置確定了。做法是:右端點優先排序。注意我們這麼做的前提是:從左到右遍歷線段。
這裏還存在一個問題,就是是不是第i條線段就可以放第i個點。容易想到,如果是(1,3)(1,3)(2,2)這樣的線段,那麼我們應當先把2這個位置放了,也就是說,第一條線段對應的點是第二個。所以不確定一條線段應該放在哪個點上,我們就應該遍歷這條線段上的點,第一個還沒有放車的點就是當前線段應該放車的點。

【參考代碼】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=5000+100;
int N;

struct Line{
      int p0,p1,pos;
      int r,c;
      void sets( int  p0, int p1, int pos ){  this->p0=p0; this->p1=p1; this->pos=pos;  }
};
int cmp1( Line a, Line b  )
{
      return a.p1<b.p1 || (  a.p1==b.p1 && a.p0<b.p0 );
}
int cmp2(  Line a, Line b ){   return a.pos<b.pos;  }

Line row[maxn],column[maxn];



void solve()
{
      int visr[maxn],visc[maxn];
      memset( visr, 0, sizeof visr );
      memset( visc,0,sizeof visc );
      for( int i=1; i<=N; i++ )
      {
            bool ok=false;
            for( int j=row[i].p0; j<=row[i].p1; j++ )
            {
                  if( !visr[j] ) { visr[j]=1;  row[i].r=j; ok=true; break;  }
            }
            if( !ok ) {  printf( "IMPOSSIBLE\n" ); return;  }
            ok=false;
            for( int j=column[i].p0; j<=column[i].p1; j++ )
            {
                  if( !visc[j]  ) {  visc[j]=1;  column[i].c=j; ok=true; break; }
            }
            if( !ok ) {  printf( "IMPOSSIBLE\n" ); return;  }
      }
      sort(  row+1, row+1+N, cmp2 );
      sort( column+1, column+1+N,cmp2 );
      for( int i=1; i<=N; i++ )
      {
            printf( "%d %d\n",row[i].r,column[i].c );
      }
}


int main()
{
      while(  ~scanf( "%d",&N )  && N )
      {
           for( int i=1; i<=N; i++ )
           {
                 int x1,y1,x2,y2; scanf( "%d%d%d%d",&x1,&y1,&x2,&y2 );
                 row[i].sets(  x1,x2,i  );
                 column[i].sets( y1,y2,i );
           }
           sort(  row+1,row+N+1,cmp1 );
           sort( column+1,column+1+N,cmp1 );
           solve();
      }
      return 0;
}








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章