测试4T3 围栏问题
围栏问题
时间限制: 2 Sec 内存限制: 128 MB
题目描述
在一片草原上,有n只兔子无忧无虑地生活着。这片草原可以划分成m×m的方阵。每个方格内最多有一只兔子。
一位饲养员负责喂养这些兔子。为了方便,她需要用篱笆建造最多k座围栏,将草原上的兔子全部围起来。
围栏需要满足以下条件:
(1)必须沿着网格线建造;
(2)每座围栏是一个不与自身重叠或相交的封闭回路;
(3)各座围栏之间互相不重叠、不相交;
(4)一座围栏不能被围在另一座围栏里面。
请你帮助饲养员计算一下围栏总长度的最小值。
输入
输入文件名为fence.in
输入第1行为三个整数m,k,n。
接下来n行每行为一对正整数x,y,表示第x行第y列的方格中有一只兔子。
输出
输出文件名为fence.out
输出仅1行,为一个正整数,表示围栏总长度的最小值。
样例输入
【输入输出样例1】
fence.in
6 1 4
1 3
4 2
4 4
6 4
fence.out
18
样例输出
【输入输出样例2】
fence.in
6 2 4
1 3
4 2
4 4
6 4
fence.out
16
这道题因为时间不多了,就打了k=1,2时的情况,就记录一下行列上的最大(小)值,加一加除以二,在判断从哪个节点断开。
其实100分的思想也差不多,就是DFS一下,记录当前是第几个数,枚举其在哪个集合,当前最小花费是多少
代码是找了一份,风格极好:http://www.cnblogs.com/the-unbeatable/p/6902532.html
贴一下标程
#include<iostream> #include<cstdio> #include<algorithm> #define N 17 using namespace std; int xx[N],yy[N],n,m,k,lx[N],ly[N],rx[N],ry[N],ans; void dfs(int now,int set,int cost) { if(cost>ans) return; if(now>n)ans=min(ans,cost); if(set<k) { ++set; lx[set]=rx[set]=xx[now]; ly[set]=ry[set]=yy[now]; dfs(now+1,set,cost+4); lx[set]=rx[set]=ly[set]=ry[set]; set--; } int ax,ay,bx,by,spend; for(int i=1;i<=set;i++) { int ax=lx[i],ay=ly[i],bx=rx[i],by=ry[i]; int nz=cost-2*(bx-ax+1+by-ay+1); lx[i]=min(lx[i],xx[now]); rx[i]=max(rx[i],xx[now]); ly[i]=min(ly[i],yy[now]); ry[i]=max(ry[i],yy[now]); nz+=2*(ry[i]-ly[i]+1+rx[i]-lx[i]+1); dfs(now+1,set,nz); lx[i]=ax,ly[i]=ay,rx[i]=bx,ry[i]=by; } } int main() { ios::sync_with_stdio(false); cin>>m>>k>>n; for(int i=1;i<=n;i++) { cin>>xx[i]>>yy[i]; } ans=1e9; dfs(1,0,0); printf("%d\n",ans); return 0; }