围栏问题 [搜索+最优化剪枝]


Solutionmathcal{Solution}

不合法方案的花费一定比最优解大

有了这条隐含信息, 直接搜索, 方法如下 ,

  • 按顺序给每只兔子安排围墙,
  • 设当前搜到了 kk 只兔子, 有两个选择.
  1. 扩张前面所存在的围栏
  2. 只围住自己

加上 最优化剪枝 即可 ACAC.


#include<bits/stdc++.h>
#define reg register

int read(){
        char c;
        int s = 0, flag = 1;
        while((c=getchar()) && !isdigit(c))
                if(c == '-'){ flag = -1, c = getchar(); break ; }
        while(isdigit(c)) s = s*10 + c-'0', c = getchar();
        return s * flag;
}

const int maxn = 25;

int M;
int K;
int N;
int Ans;
int min_x[maxn];
int min_y[maxn];
int max_x[maxn];
int max_y[maxn];

struct Rabbit{ int x, y; } A[maxn];

void DFS(int k, int cnt, int sum){
        if(sum >= Ans) return ;
        if(k > N){ Ans = sum; return ; }
        if(cnt < K){ 
                min_x[cnt+1] = max_x[cnt+1] = A[k].x; 
                min_y[cnt+1] = max_y[cnt+1] = A[k].y;
                DFS(k+1, cnt+1, sum + 4);
        }
        if(k == 1) return ;
        for(reg int i = 1; i <= cnt; i ++){
                int tx = A[k].x, ty = A[k].y;
                int t_1 = min_x[i], t_2 = min_y[i], t_3 = max_x[i], t_4 = max_y[i];
                int tmp = 2*(max_x[i]-min_x[i]+max_y[i]-min_y[i]);
                min_x[i] = std::min(tx, min_x[i]);
                min_y[i] = std::min(ty, min_y[i]);
                max_x[i] = std::max(tx, max_x[i]);
                max_y[i] = std::max(ty, max_y[i]);
                tmp = 2*(max_x[i]-min_x[i]+max_y[i]-min_y[i]) - tmp;
                DFS(k+1, cnt, sum + tmp);
                min_x[i] = t_1, min_y[i] = t_2, max_x[i] = t_3, max_y[i] = t_4;
        }
}

int main(){
        M = read(); K = read(); N = read();
        for(reg int i = 1; i <= N; i ++)
                A[i].x = read(), A[i].y = read();
        Ans = 0x3f3f3f3f;
        DFS(1, 0, 0);
        printf("%d
", Ans);
        return 0;
}
原文地址:https://www.cnblogs.com/zbr162/p/11822609.html