栅栏里的葱

【问题描述】


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


【输入格式】


第一行三个整数?,?,?。
接下来?行每行两个整数?,?代表某棵葱的位置。


【输出格式】


一行一个整数代表答案。


【样例输入 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


【样例解释】


你猜树上有啥,有钟神呗。

 

【数据规模与约定】


1= 1 32。
60%的数据,? ≤ 10。
对于100%的数据,1 ≤ ? ≤ ? ≤ 16,? ≤ 1000。

 

 

思路:

  搜索+剪枝+卡时

  但是,只有95分

  作为蒟蒻的ac不过去了

  写篇随笔然后继续下一题

  搜索的话有两种

  1.搜索每个栅栏放哪几根葱

  2.搜索每根葱放在哪个栅栏里

  先看第一种方法

  搜索哪个栅栏放哪几根葱

  这个方法不仅恶心而且麻烦还要记录多个状态

  所以,果断放弃

  第二种方法

  一根葱对应着一个栅栏,只有这一种搜索状态

  相比第一种方法无疑是一种非常简单且省事的方法

  果断选择第二种

  因为是要求最小的ans

  所以唯一的一个剪枝就是

  if(当前长度>=ans) return;

  ans初始赋极大值

 

  来,上代码:

#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>

using namespace std;

struct node {
    int x,y;
};
struct node ci[1001];

int n,k,m,ans=0x7fffff,up[20],down[20],l[20],r[20],pd[20];

int max(int a,int b){return a>b?a:b;}

int min(int a,int b){return a<b?a:b;}

bool check(int from,int kcc)
{
    for(int i=1;i<=n;i++)
    {
        if(i==from) continue;
        if(pd[i]==1)
        {
            if(ci[kcc].x<=up[i]&&ci[kcc].x>=down[i]&&ci[kcc].y<=r[i]&&ci[kcc].y>=l[i])
            return true;
        }
    }
    return false;
}

int lenth()
{
    int cur=0;
    for(int i=1;i<=k;i++) if(pd[i]==1)
        cur+=(down[i]-up[i]+1+r[i]-l[i]+1)*2;
    return cur;
}

void dfs(int now)
{
    if(clock()>=1980){
        printf("%d\n",ans);
        exit(0);
    }
    int cur=lenth();
    if(cur>=ans) return ;
    if(now==n+1)
    {
        ans=cur;
        return ;
    }
    int iup,idown,il,ir;
    for(int i=1;i<=k;i++)
    {
        if(check(i,now)) continue;
        iup=up[i];
        idown=down[i];
        il=l[i];
        ir=r[i];
        up[i]=min(ci[now].x,up[i]);
        down[i]=max(ci[now].x,down[i]);
        l[i]=min(ci[now].y,l[i]);
        r[i]=max(ci[now].y,r[i]);
        if(pd[i]==0)
        {
            pd[i]=1;
            dfs(now+1);
            pd[i]=0;
        }
        else dfs(now+1);
        up[i]=iup;
        down[i]=idown;
        l[i]=il;
        r[i]=ir;
    }
}

int main()
{
    scanf("%d%d%d",&m,&k,&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&ci[i].x,&ci[i].y);
    memset(up,127/3,sizeof(up));
    memset(down,-1,sizeof(down));
    memset(l,127/3,sizeof(l));
    memset(r,-1,sizeof(r));
    dfs(1);
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2016-11-08 07:55  IIIIIIIIIU  阅读(240)  评论(0编辑  收藏  举报