栅栏围大葱 dan

来源:互联网 发布:java file.getname 编辑:程序博客网 时间:2024/04/29 19:34

问题描述
m*m的方阵上有棵葱,你要修一些栅栏把它们围起来。一个栅栏是一段沿着网格建造的封闭图形(即要围成一圈)。各个栅栏之间应该不相交、不重叠且互相不包含。如果你最多修k个栅栏,那么所有栅栏的长度之和最小是多少?

输入格式
第一行三个整数n,m,k。
接下来n行每行两个整数代表某棵葱的位置。

输出格式
一行一个整数代表答案。

样例输入1
6 1 4
1 3
4 2
4 4
6 4
样例输出1
18

样例输入2
6 2 4
1 3
4 2
4 4
6 4
样例输出2
16
样例解释
你猜树上有啥.

这里写图片描述

搜索+奇妙的卡时竟然可以过。

通过画图可以知道,围成不规则的图形和围成矩形花的代价是一样的,这就把代码难度降低了好多。

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#include<queue>#include<ctime>#define inf 1000000000#define LL long longusing namespace std;int x[50],y[50],n,m,k;int ans;int sx[50],sy[50],mx[50],my[50],a[50];void dfs(int t)//搜索每棵葱在哪个栅栏中{    if(clock()>1970) //加上卡时,莫名地过了,这时已经更新出答案了??     {        printf("%d",ans);        exit(0);    }    if(t>n)     {        int sum=0;        for(int i=1;i<=k;i++)        {            if(a[i]) sum+=(mx[i]-sx[i]+1)*2+(my[i]-sy[i]+1)*2;        }        ans=min(ans,sum);        return;    }    int sum=0;    for(int i=1;i<=k;i++)    {        if(a[i]) sum+=(mx[i]-sx[i]+1)*2+(my[i]-sy[i]+1)*2;        if(sum>=ans) return;//最优化剪枝     }    for(int i=1;i<=k;i++)    {        int qx=sx[i],qy=sy[i],px=mx[i],py=my[i];        sx[i]=min(sx[i],x[t]);        sy[i]=min(sy[i],y[t]);        mx[i]=max(mx[i],x[t]);        my[i]=max(my[i],y[t]);        a[i]++;        dfs(t+1);        a[i]--;        sx[i]=qx;sy[i]=qy;        mx[i]=px;my[i]=py;    } }int main(){    freopen("dan.in","r",stdin);    freopen("dan.out","w",stdout);    memset(sx,127,sizeof(sx));    memset(sy,127,sizeof(sy));    scanf("%d%d%d",&m,&k,&n);    for(int i=1;i<=n;i++)     scanf("%d%d",&x[i],&y[i]);    ans=inf;    dfs(1);    printf("%d",ans);    return 0;}
原创粉丝点击