测试4T3 围栏问题

围栏问题

时间限制: 2 Sec  内存限制: 128 MB

题目描述

在一片草原上,有n只兔子无忧无虑地生活着。这片草原可以划分成m×m的方阵。每个方格内最多有一只兔子。

一位饲养员负责喂养这些兔子。为了方便,她需要用篱笆建造最多k座围栏,将草原上的兔子全部围起来。

围栏需要满足以下条件:

(1)必须沿着网格线建造;

(2)每座围栏是一个不与自身重叠或相交的封闭回路;

(3)各座围栏之间互相不重叠、不相交;

(4)一座围栏不能被围在另一座围栏里面。

请你帮助饲养员计算一下围栏总长度的最小值。

输入

输入文件名为fence.in

输入第1行为三个整数mkn

接下来n行每行为一对正整数xy,表示第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
",ans);
    return 0;
}
 
 
原文地址:https://www.cnblogs.com/dancer16/p/7039357.html