UVa 11134 Fabled Rooks 虛擬的車 - 貪心+思維

給一個n x n的棋盤,要求在上面放n個車且相互不攻擊,而且對於第i個車要求必須在給定的矩形中(每個車所對應的矩形已給出),求一組滿足的解,無滿足的情況輸出”IMPOSSIBLE”

首先考慮拆點,將二維座標拆成x軸和y軸的兩組,對於每一個軸要求在給定的n個線段上選出一個1~n的排列。

如果考慮每條線段只能選擇一個數,每個數的選擇只能取一次,滿足二分圖的性質,可以考慮拿最大匹配寫(寫了個Hangary然後就T了一屏,Dinic或者HC可能會好點,懶得寫了)

只能貪心了。研究紫書發現一個很有趣的思路,就是線段之間的包含關係。若某一線段被包含,則這個線段一定比包含他的大區間先要被考慮。線段之間包含關係作爲突破口解決貪心問題的情況很常見。
先考慮大區間包含小區間的情況,大區間很明顯比小區間的滿足可能更大,優先考慮小區間總不會更差,於是對於一個區間,先忽略所有嵌套它的大區間。於是先拋開大區間,剩下的都是不相容的小區間,這些小區間從左向右排序,對於每一個區間可能優先考慮靠左的沒有用過的點。當一個大區間內的所有小區間都被討論完後再討論大區間,思考實現的方式,即如何排序可以做到這一點:
先按右端點升序,再左端點降序,這樣可以保證小區間絕對在大區間之前,而且不相容的小區間本身有序。(都是套路啊啊啊)

然後附上WA了n次才調對的代碼:

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm> 

using namespace std;

const int maxn=5005;

struct node
{
    int x,y,id;
    bool operator < (const node &tmp) const
    {
        return y<tmp.y||(y==tmp.y&&x>tmp.x);
    }
}qx[maxn],qy[maxn];

int n,linkx[maxn],linky[maxn];
bool flag,vst[maxn];

void solve(node q[],int link[])
{
    sort(q+1,q+n+1);
    memset(vst+1,0,sizeof(bool)*n);
    for(int i=1;i<=n;i++)
    {
        int pos=q[i].x;
        while(pos<=q[i].y&&vst[pos])pos++;
        if(pos<=q[i].y)link[q[i].id]=pos,vst[pos]=true;
        else{flag=false;return;}
    }
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        flag=true;
        for(int i=1;i<=n;i++)
            scanf("%d%d%d%d",&qx[i].x,&qy[i].x,&qx[i].y,&qy[i].y),
            qx[i].id=qy[i].id=i;
        solve(qx,linkx);
        solve(qy,linky);
        if(!flag){puts("IMPOSSIBLE");continue;}
        for(int i=1;i<=n;i++)
            printf("%d %d\n",linkx[i],linky[i]);
    }
    return 0;
}

外加一份Hangary(TLE):

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm> 

using namespace std;

const int maxn=5005;

struct node
{
    int x,y;
}qx[maxn],qy[maxn];
struct edge
{
    int to,next;
}e[maxn*maxn];

int n,cnt,T;
int head[maxn],matchx[maxn],matchy[maxn],vst[maxn];

void insert(int a,int b)
{
    e[++cnt].to=b;e[cnt].next=head[a];head[a]=cnt;
}
bool find(int x,int match[])
{
    int y;
    for(int i=head[x];i;i=e[i].next)if(vst[y=e[i].to]!=T)
    {
        vst[y]=T;
        if(!match[y]||find(match[y],match))
        {
            match[y]=x;
            return true;
        }
    }
    return false;
}
int hangary(node q[],int match[])
{
    cnt=0;
    int num=0;
    memset(head+1,0,sizeof(int)*n);
    memset(vst+1,0,sizeof(int)*n);
    memset(match+1,0,sizeof(int)*n);
    for(int i=1;i<=n;i++)
    {
        for(int j=q[i].x;j<=q[i].y;j++)
        insert(j,i);
    }
    for(int i=1;i<=n;i++)T=i,num+=find(i,match);
    if(num<n)return false;
    return true;
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        for(int i=1;i<=n;i++)
            scanf("%d%d%d%d",&qx[i].x,&qy[i].x,&qx[i].y,&qy[i].y);
        if(hangary(qx,matchx)&&hangary(qy,matchy))
            for(int i=1;i<=n;i++)printf("%d %d\n",matchx[i],matchy[i]);
        else puts("IMPOSSIBLE");
    }
    return 0;
}

閒得蛋疼又交了一波網絡流然後又T了。。。

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm> 

using namespace std;

const int maxn=5005;

struct node
{
    int x,y;
}qx[maxn],qy[maxn];
struct edge
{
    int to,next,val;
}e[(maxn*maxn)<<1];

int n,cnt,T;
int head[maxn<<1],matchx[maxn],matchy[maxn],depth[maxn<<1];

#define S 0
#define T (n<<1)+1

void insert(int a,int b)
{
    e[++cnt].to=b;e[cnt].next=head[a];e[cnt].val=1;head[a]=cnt;
    e[++cnt].to=a;e[cnt].next=head[b];e[cnt].val=1;head[b]=cnt;
}
bool bfs()
{
    queue<int>q;
    q.push(S);
    memset(depth,0,sizeof depth);
    depth[S]=1;
    while(!q.empty())
    {
        int u=q.front(),v;q.pop();
        for(int i=head[u];i;i=e[i].next)
            if(!depth[v=e[i].to]&&e[i].val)
            {
                depth[v]=depth[u]+1;
                q.push(v);
            }
    }   
    return depth[T];
}
int dfs(int match[],int x,int a)
{
    if(x==T||a==0)return a;
    int rest=a,y;
    for(int i=head[x];i;i=e[i].next)
        if(depth[y=e[i].to]==depth[x]+1&&e[i].val)
    {
        int cur=dfs(match,y,min(rest,e[i].val));
        e[i].val-=cur;
        e[i^1].val+=cur;
        if(y>n&&cur&&(~i&1))match[y-n]=x;
        rest-=cur;
        if(!rest)return a;
    }
    return a-rest;
}
int dinic(node q[],int match[])
{
    cnt=1;
    int num=0;
    memset(head,0,sizeof head);
    memset(match+1,0,sizeof(int)*n);
    for(int i=1;i<=n;i++)
    {
        for(int j=q[i].x;j<=q[i].y;j++)
            insert(j,i+n);
    }
    for(int i=1;i<=n;i++)
        insert(S,i),insert(i+n,T);
    int res=0;
    while(bfs())
        res+=dfs(match,S,0x3f3f3f3f);
    return res>=n;
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        for(int i=1;i<=n;i++)
            scanf("%d%d%d%d",&qx[i].x,&qy[i].x,&qx[i].y,&qy[i].y);
        if(dinic(qx,matchx)&&dinic(qy,matchy))
            for(int i=1;i<=n;i++)printf("%d %d\n",matchx[i],matchy[i]);
        else puts("IMPOSSIBLE");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章