题目描述
在一片草原上,有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
提示
【输入输出样例解释1】
如图是一种满足题意的建造方法。
【输入输出样例解释2】
如图是一种满足题意的建造方法。
【数据范围】
对于10%的数据,k=1;
对于10%~30%的数据,k=2;
对于30%~60%的数据,n≤10;
对于100%的数据,1≤k≤n≤16,m≤1,000。
solution:
看到“1<=k<=n<=16”,这个数据非常小,所以可以直接搜索,加上最优性,就可以ac了。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
int m,k,n,x[100],y[100],a[100],b[100],c[100],d[100],ans;
void dfs(int t,int num,int sum){
if(sum>ans)
return;
if(t>n){
ans=sum;
return;
}
if(num<k){
a[num+1]=x[t];
b[num+1]=y[t];
c[num+1]=x[t];
d[num+1]=y[t];
dfs(t+1,num+1,sum+4);
a[num+1]=b[num+1]=c[num+1]=d[num+1]=0;
}
int aa,bb,cc,dd;
for(int i=1;i<=num;i++){
aa=a[i];
bb=b[i];
cc=c[i];
dd=d[i];
a[i]=min(a[i],x[t]);
b[i]=min(b[i],y[t]);
c[i]=max(c[i],x[t]);
d[i]=max(d[i],y[t]);
dfs(t+1,num,sum-2*(cc-aa+1+dd-bb+1)+2*(c[i]-a[i]+1+d[i]-b[i]+1));
a[i]=aa;
b[i]=bb;
c[i]=cc;
d[i]=dd;
}
}
int main(){
scanf("%d%d%d",&m,&k,&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&x[i],&y[i]);
ans=1000000000;
dfs(1,0,0);
printf("%d\n",ans);
return 0;
}