XJOI2061围栏问题【深度优先搜索】

围栏问题

在一片草原上,有n只兔子无忧无虑地生活着。这片草原可以划分成m×m的方阵。每个方格内最多有一只兔子。
一位饲养员负责喂养这些兔子。为了方便,她需要用篱笆建造最多k座围栏,将草原上的兔子全部围起来。
围栏需要满足以下条件:
(1)必须沿着网格线建造;
(2)每座围栏是一个不与自身重叠或相交的封闭回路;
(3)各座围栏之间互相不重叠、不相交;
(4)一座围栏不能被围在另一座围栏里面。
请你帮助饲养员计算一下围栏总长度的最小值。

输入格式:

输入文件名为fence.in
输入第1行为三个整数m,k,n。
接下来n行每行为一对正整数x,y,表示第x行第y列的方格中有一只兔子。

输出格式:

输出文件名为fence.out
输出仅1行,为一个正整数,表示围栏总长度的最小值。

样例输入:

样例1
6 1 4
1 3
4 2
4 4
6 4
样例2
6 2 4
1 3
4 2
4 4
6 4

样例输出:

样例1
18
样例2
16

数据范围:

对于10%的数据,k=1;
对于10%~30%的数据,k=2;
对于30%~60%的数据,n≤10;
对于100%的数据,1≤k≤n≤16,m≤1,000。

时间限制:

1S

空间限制:

128M

考虑到围栏数和兔子数如此之少,可以暴搜,枚举一只兔子加入前面那个围栏,或是自建围栏.

至于相交与包围的问题不用考虑,这两种情况做出来一定不是最优解.

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 const int N=17;
 5 int xx[N],yy[N],n,m,k;
 6 int lx[N],ly[N],rx[N],ry[N],ans=2e9;
 7 inline void dfs(int x,int y,int z)
 8 {
 9     if(z>ans) return;
10     if(x>n)
11     {
12         ans=z;
13         return;
14     }
15     if(y<k)
16     {
17         rx[y+1]=lx[y+1]=xx[x];
18         ry[y+1]=ly[y+1]=yy[x];
19         dfs(x+1,y+1,z+4);
20         rx[y+1]=lx[y+1]=0;
21         ry[y+1]=ly[y+1]=0;
22     }
23     int ax,ay,bx,by,nz;
24     for(int i=1;i<=y;i++)
25     {
26         ax=lx[i];
27         ay=ly[i];
28         bx=rx[i];
29         by=ry[i];
30         nz=z-2*((bx-ax+1)+(by-ay+1));
31         lx[i]=min(xx[x],lx[i]);
32         rx[i]=max(xx[x],rx[i]);
33         ly[i]=min(yy[x],ly[i]);
34         ry[i]=max(yy[x],ry[i]);
35         nz+=2*((rx[i]-lx[i]+1)+(ry[i]-ly[i]+1));
36         dfs(x+1,y,nz);
37         lx[i]=ax;
38         ly[i]=ay;
39         rx[i]=bx;
40         ry[i]=by;
41     }
42 }
43 int main()
44 {
45     scanf("%d%d%d",&m,&k,&n);
46     for(int i=1;i<=n;i++) scanf("%d%d",&xx[i],&yy[i]);
47     dfs(1,0,0);
48     printf("%d\n",ans);
49     return 0;
50 }
时间: 2024-11-07 18:44:13

XJOI2061围栏问题【深度优先搜索】的相关文章

深度优先搜索与广度优先搜索算法理解

深度优先搜索算法和广度优先搜索算法是图论中两个有意思也很实用的算法,下面我们来看看这两个算法. 严书中,给出的利用深度优先搜索(Deep First Search)算法进行图的遍历伪码如下 1 Boolean visited[MAX]; //标志数组 2 Status (*VisitFunction)(int v); //访问函数 3 4 void DFSTraverse(Graph G, Status (*Visit)(int v)) 5 { 6 VisitFunction = Visit;

图论 深度优先搜索 广度优先搜索的非递归实现

深度优先遍历 1.深度优先遍历的递归定义 假设给定图G的初态是所有顶点均未曾访问过.在G中任选一顶点v为初始出发点(源点),则深度优先遍历可定义如下:首先访问出发点v,并将其标记为已访问过:然后依次从v出发搜索v的每个邻接点w.若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止.若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止. 图的深度优先遍历类似于树的

深度优先搜索

在图中的深度优先搜索,由于避免回路的产生,设置visit数组. 有两种深度优先的应用场景.一种是用于最优解的寻找,即到达目的地的最优解.这时需要设置全局的一个数组,还有变量,来储存路径.通过与别的方法的比较,获取最优解. 第二种是染色问题,只要求全部遍历,没有最优的要求. 还有哈希的用法.当需要记录拥有共同数字特征的一些属性时,就可以使用哈希数组.使用时按照属性的含义寻找.如二叉树某层的数量.

深度优先搜索(dfs)

关于深度优先搜索的总结: 1 dfs 的基本结构:  void dfs(int x){ if( x 超出边界){ return ; }else{ for(遍历){ if(未访问过){ 访问         ; 打上标记    ; dfs(x + 1) ; 去掉标记    ; //极易忘记 } } } return; } 2 用dfs求全排列: 本来好好的,结果sizeof(pointer) 就完蛋了.神秘的内存错误,而且还能正常的跑出一个不正常的结果出来. 想了解sizeof这个小妖精的看这里

深度优先搜索思想初体验

1.求数字 1~n 的全排列 import java.util.Scanner ; public class Permutation{ //求数字 1~n 的全排列: int[] array ; int[] book ; int n ; public void permutation(int step){ // 深度优先搜索思想: if (step==n+1) { for (int i=1;i<=n;i++) { System.out.print(array[i] + " ")

深度优先搜索(DFS)

定义: (维基百科:https://en.wikipedia.org/wiki/Depth-first_search) 深度优先搜索算法(Depth-First-Search),是搜索算法的一种.是沿着树的深度遍历树的节点,尽可能深的搜索树的分支.当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点.这一过程一直进行到已发现从源节点可达的所有节点为止.如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止(属于盲目搜索). 基

图的遍历之深度优先搜索(DFS)

深度优先搜索(depth-first search)是对先序遍历(preorder traversal)的推广.”深度优先搜索“,顾名思义就是尽可能深的搜索一个图.想象你是身处一个迷宫的入口,迷宫中的路每一个拐点有一盏灯是亮着的,你的任务是将所有灯熄灭,按照DFS的做法如下: 1. 熄灭你当前所在的拐点的灯 2. 任选一条路向前(深处)走,每经过一个拐点将灯熄灭直到与之相邻的拐点的灯全部熄灭后,原路返回到某个拐点的相邻拐点灯是亮着的,走到灯亮的拐点,重复执行步骤1 3. 当所有灯熄灭时,结束 将

图算法系列-深度优先搜索与广度优先搜索

2.深度优先搜索 为了访问一个顶点,我们将它标记为已经访问过,然后递归的访问所有与子邻接的并且尚未标记的顶点,这就是深度优先搜索(DFS),DFS常用于解决路径问题. 比如下面的连通图,我们从顶点0开始对图进行探索 下面这个图显示了DFS处理时的递归调用树. DFS可以解决的问题:1)环检测:一个图中有环吗?该图是森林吗?2)简单路径:给定两个顶点,是否存在一条连接他们的路径3)简单连通性:无论何时使用DFS,都可以在线性时间内确定一个图是否连通4)顶点搜索:在给定顶点所在的同一个连通分量中有多

[ACM] 1016 Prime Ring Problem (深度优先搜索)

Prime Ring Problem Problem Description A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime. Note: the number of first circle

完全二叉树深度优先搜索

题目 使用一个长度为N的数组,1<=N<=50,存储一棵完全二叉树.(二叉树中每个节点最多有两个子树称为左子树和右子树.完全二叉树是除最后一层外,每一层上的节点数均达到最大值:在最后一层上只缺少右边的若干节点.在数组中,如果以下标1为起始位置,那么每个节点的左儿子是其自己下标乘以2的节点,右儿子是自己下标乘以2加1的节点,即arr[i*2]和arr[i*2+1]是arr[i]的左右儿子.)然后使用左子树优先的深度优先搜索方法搜索一棵完全二叉树中的一个值为X的节点,最终输出其深度优先搜索的过程,