围栅栏

赌上一切的95分!

源代码:

#include<cstdio>
#include<ctime>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int m,n,k,Ans=1000000000,X[25],Y[25],i[25],Lx[25],Ly[25],Rx[25],Ry[25]; //这些都是上左下右角标。
void DFS(int t) //暴力搜索,t表示葱数。
{
    if (clock()>=1950) //丧心病狂!不过我喜欢- -。
    {
        printf("%d",Ans);
        exit(0);
    }
    if (t>n) //围好了。
    {
        int Sum(0);
        for (int a=1;a<=k;a++)
          if (i[a]) //修了此栅栏。
            Sum+=(Rx[a]-Lx[a]+Ry[a]-Ly[a]+2)<<1;
        Ans=min(Ans,Sum);
        return;
    }
    int Sum(0);
    for (int a=1;a<=k;a++)
      if (i[a])
        Sum+=(Rx[a]-Lx[a]+Ry[a]-Ly[a]+2)<<1;
    if (Sum>=Ans) //剪枝。
      return;
    for (int a=1;a<=k;a++) //仔细想一想这种搜索方法,发现可以像多维循环一样,涵盖所有情况。
    {
        int t1=Lx[a],t2=Ly[a];
        int T1=Rx[a],T2=Ry[a];
        Lx[a]=min(Lx[a],X[t]),Ly[a]=min(Ly[a],Y[t]);
        Rx[a]=max(Rx[a],X[t]),Ry[a]=max(Ry[a],Y[t]);
        i[a]++;
        DFS(t+1);
        Lx[a]=t1,Ly[a]=t2;
        Rx[a]=T1,Ry[a]=T2;
        i[a]--;
    }
}
int main()
{
    memset(Lx,0x3f,sizeof(Lx));
    memset(Ly,0x3f,sizeof(Ly)); //初始化。
    scanf("%d%d%d",&m,&k,&n);
    for (int a=1;a<=n;a++)
      scanf("%d%d",&X[a],&Y[a]);
    DFS(1);
    printf("%d",Ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Ackermann/p/6012596.html