HDU 5046 Airport(dlx)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5046

题意:n个城市修建m个机场,使得每个城市到最近进场的最大值最小。

思路:二分+dlx搜索判定。

#include <iostream>
#include <map>
#include <string>
#include <stdio.h>
#include <vector>
#include <set>
#include <algorithm>
#include <string.h>
#include <fstream>
#include <tchar.h>
#include <sstream>
using namespace std;



int visit[6666];
int KK;
int m;


class CDancingLinks
{
protected:
    struct DancingLinksNode
    {
        DancingLinksNode* left;
        DancingLinksNode* right;
        DancingLinksNode* down;
        DancingLinksNode* up;
        int col;
        int row;
    };

    typedef DancingLinksNode Node;

    int *m_columnEleNumbers;
    int m_colNumber;
    int m_rowNumber;
    Node* m_pool;
    Node** m_head;
    int m_curUsePoolIndex;





    void _Remove(Node* cur)
    {
        --m_columnEleNumbers[cur->col];
        for(Node* p=cur->down;p!=cur;p=p->down)
        {
            p->left->right=p->right;
            p->right->left=p->left;
        }
    }

    void _Resume(Node* cur)
    {
        ++m_columnEleNumbers[cur->col];
        for(Node* p=cur->up;p!=cur;p=p->up)
        {
            p->left->right=p;
            p->right->left=p;
        }
    }

    int astar()
    {
        Node* p=_GetNode(0);


        ++KK;
        int ans=0;

        for(Node* q=p->left;q!=p;q=q->left) if(KK!=visit[q->col])
        {
            visit[q->col]=KK;
            ++ans;
            for(Node* r=q->up;r!=q;r=r->up) for(Node* t=r->left;t!=r;t=t->left)
            {
                visit[t->col]=KK;
            }
        }
        return ans;
    }

    bool _SearchSolution(const int depth,std::vector<int> &solution)
    {
        Node* p=_GetNode(0);
        if(p->left==p) return true;
        if(depth+astar()>m) return false;


        int Min=m_rowNumber+1;
        int MinColumnIndex=0;
        for(Node* q=p->left;q!=p;q=q->left)
        {
            if(m_columnEleNumbers[q->col]<Min)
            {
                Min=m_columnEleNumbers[q->col];
                MinColumnIndex=q->col;
            }
        }


        for(Node* q=_GetNode(MinColumnIndex)->down;q!=_GetNode(MinColumnIndex);q=q->down)
        {
            _Remove(q);
            solution.push_back(q->row);
            for(Node* rr=q->right;rr!=q;rr=rr->right) _Remove(rr);
            if(_SearchSolution(depth+1,solution)) return true;
            for(Node* rr=q->left;rr!=q;rr=rr->left) _Resume(rr);
            solution.pop_back();
            _Resume(q);
        }

        return false;
    }

    Node* _GetNode(int id) { return m_pool+id; }

    void _ReleaseMemory()
    {
         if(m_columnEleNumbers)
        {
            delete[] m_columnEleNumbers;
            m_columnEleNumbers=nullptr;
        }

        if(m_pool)
        {
            delete[] m_pool;
            m_pool=nullptr;
        }
        if(m_head)
        {
            delete[] m_head;
            m_head=nullptr;
        }
    }

public:

    CDancingLinks():m_colNumber(-1),m_rowNumber(-1),
        m_columnEleNumbers(nullptr),m_pool(nullptr),m_head(nullptr) {}

    /***
      列下标为[1,Column]
    ***/
    CDancingLinks(const int Column,const int Row):
        m_columnEleNumbers(nullptr),m_pool(nullptr),m_head(nullptr)
    {
        SetSize(Column,Row);
    }

    /***
      列下标为[1,Column]
    ***/
    void SetSize(const int Column,const int Row)
    {
        m_colNumber=Column;
        m_rowNumber=Row;

        _ReleaseMemory();

        m_columnEleNumbers=new int[m_colNumber+1];
        m_pool=new Node[m_colNumber*(m_rowNumber+1)+1];
        m_head=new Node*[m_rowNumber+1];
        Clear();
    }

    void Clear()
    {
        for(int i=0;i<=m_colNumber;++i)
        {
            Node* cur=_GetNode(i);
            cur->left=((i==m_colNumber)?_GetNode(0):_GetNode(i+1));
            cur->right=((0==i)?_GetNode(m_colNumber):_GetNode(i-1));
            m_columnEleNumbers[i]=0;

            cur->up=cur->down=_GetNode(i);
            cur->col=i;
            cur->row=0;
        }
        for(int i=1;i<=m_rowNumber;++i) m_head[i]=NULL;
        m_curUsePoolIndex=m_colNumber+1;
    }

    ~CDancingLinks()
    {
        _ReleaseMemory();
    }

    void AddElement(const int row,const int col)
    {

        Node* cur=m_pool+(m_curUsePoolIndex++);

        cur->up=_GetNode(col);
        cur->down=_GetNode(col)->down;
        m_pool[col].down->up=cur;
        m_pool[col].down=cur;


        if(m_head[row]==NULL)
        {
            m_head[row]=cur->left=cur->right=cur;
        }
        else
        {
            cur->left=m_head[row]->left;
            cur->right=m_head[row];
            m_head[row]->left->right=cur;
            m_head[row]->left=cur;
        }
        ++m_columnEleNumbers[col];
        cur->col=col;
        cur->row=row;
    }

    bool GetSolution(std::vector<int> &Solution)
    {
        return _SearchSolution(0,Solution);
    }
};





int a[66][2];
long long dis[66][66];
int n;
long long d[4444];

CDancingLinks A;

inline long long dist(int i,int j)
{
    return (1ll*abs(a[i][0]-a[j][0]))+abs(a[i][1]-a[j][1]);
}

int ok(long long M)
{
    A.Clear();
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(dis[i][j]<=M)
    {
        A.AddElement(i,j);
    }
    vector<int> ans;
    return A.GetSolution(ans);
}

long long cal()
{
    A.SetSize(n,n);

    int num=0;
    int i,j;
    for(i=1;i<=n;i++) for(j=1;j<=n;j++) dis[i][j]=dist(i,j),d[num++]=dis[i][j];
    sort(d,d+num);
    int M=unique(d,d+num)-d;
    int low=0,high=M-1;
    long long ans=d[high];

    while(low<=high)
    {
        int mid=(low+high)>>1;
        if(ok(d[mid])) ans=d[mid],high=mid-1;
        else low=mid+1;
    }
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    for(int i=1;i<=T;++i)
    {
        scanf("%d%d",&n,&m);
        for(int j=1;j<=n;++j) scanf("%d%d",&a[j][0],&a[j][1]);
        printf("Case #%d: %I64d\n",i,cal());
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值