题目链接: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()); } }