UVA 10160 Servicing Stations(深搜 + 剪枝)
Problem D: Servicing stations
A company offers personal computers for sale in N towns (3 <= N <= 35). The towns are denoted by 1, 2, ..., N. There are direct routes connecting M pairs from among these towns. The company decides to build servicing stations in several towns, so that for any town X, there would be a station located either in X or in some immediately neighbouring town of X.
Write a program for finding out the minumum number of stations, which the company has to build, so that the above condition holds.
Input
The input consists of more than one description of town (but totally, less than ten descriptions). Every description starts with number N of towns and number M of pairs of towns directly connected each other. The integers N and M are separated by a space. Every one of the next M rows contains a pair of connected towns, one pair per row. The pair consists of two integers for town's numbers, separated by a space. The input ends with N = 0 and M = 0.
Output
For every town in the input write a line containing the obtained minimum.
An example:
Input:
8 12
1 2
1 6
1 8
2 3
2 6
3 4
3 5
4 5
4 7
5 6
6 7
6 8
0 0
Output:
2
题意:给定n个城市,m种连接方式,每个城市可以放一个服务站,服务站可以覆盖本城市和与本城市连接的城市。要求最少几个服务站可以覆盖所有城市。
思路:深搜,每个服务站可以选择放与不放服务站。最多35个城市,直接搜最多要搜2^35次,所以要剪枝。。
进行了几个剪枝
1:用邻接表代替邻接矩阵来存放关系。可以减少一点搜索次数。
2:每次找到一个放置方案,保存下个数,如果之后搜索过程中个数超过这个个数。就可以直接结束这次搜索。
3:如果一个点已经搜索过了。并且该点没被覆盖到, 并且之后的点没有连接到改点,那么该点永远不会被覆盖到,就可以直接结束这条的搜索。
有一点的要注意的是。标记覆盖不能用单纯的0,1来标记。因为一个点是可以重复覆盖的。我用的是vis[] ++, vis[]--的方法来标记的
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std; int n, m;
int x, y;
int snum[40];
int map[40][40];
int f[40];
int minn; bool cmp(int a, int b)
{
return a > b;
} void dfs(int star, int num, int tnum)
{
if (tnum >= minn)
return;
if (num == n)
{
minn = tnum;
return;
}
if (star > n)
return;
for (int i = 1; i < star; i ++)
if (!f[i] && map[i][0] < star)
return;
int jia = 0;
for (int i = 0; i < snum[star]; i ++)
{
if (f[map[star][i]] == 0)
jia ++;
f[map[star][i]] ++;
}
if (jia)
dfs(star + 1, num + jia, tnum + 1);
for (int i = 0; i < snum[star]; i ++)
{
f[map[star][i]] --;
}
dfs(star + 1, num, tnum);
}
int main()
{
while (scanf("%d%d", &n, &m) != EOF && n + m)
{
minn = n;
memset(snum, 0, sizeof(snum));
memset(map, 0, sizeof(map));
memset(f, 0, sizeof(f));
for (int i = 0; i < m; i ++)
{
scanf("%d%d", &x, &y);
map[x][snum[x] ++] = y;
map[y][snum[y] ++] = x;
}
for (int i = 1; i <= n; i++)
{
map[i][snum[i] ++] = i;
sort(map[i], map[i] + snum[i], cmp);
}
dfs(1, 0, 0);
printf("%d\n", minn);
}
return 0;
}
UVA 10160 Servicing Stations(深搜 + 剪枝)的更多相关文章
- uva 10160 Servicing Stations(DFS+剪枝)
Servicing stations A company offers personal computers for sale in N towns (3 <= N <= 35). The ...
- UVA 10160 Servicing Stations(状态压缩+迭代加深)
[题目链接] LInk [题目大意] 给出一些点和边,选择一个点就能把这个点和相邻的点都覆盖,求最小点覆盖 [题解] 我们压缩点被覆盖的状态,迭代加深搜索覆盖的最小点数, 当剩余的点全部选上时都无法完 ...
- Hdu3812-Sea Sky(深搜+剪枝)
Sea and Sky are the most favorite things of iSea, even when he was a small child. Suzi once wrote: ...
- poj1190 生日蛋糕(深搜+剪枝)
题目链接:poj1190 生日蛋糕 解题思路: 深搜,枚举:每一层可能的高度和半径 确定搜索范围:底层蛋糕的最大可能半径和最大可能高度 搜索顺序:从底层往上搭蛋糕,在同一层尝试时,半径和高度都是从大到 ...
- ACM 海贼王之伟大航路(深搜剪枝)
"我是要成为海贼王的男人!" 路飞他们伟大航路行程的起点是罗格镇,终点是拉夫德鲁(那里藏匿着"唯一的大秘宝"--ONE PIECE).而航程中间,则是各式各样的 ...
- hdu 1518 Square(深搜+剪枝)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1518 题目大意:根据题目所给的几条边,来判断是否能构成正方形,一个很好的深搜应用,注意剪枝,以防超时! ...
- POJ-1724 深搜剪枝
这道题目如果数据很小的话.我们通过这个dfs就可以完成深搜: void dfs(int s) { if (s==N) { minLen=min(minLen,totalLen); return ; } ...
- 一本通例题-生日蛋糕——题解<超强深搜剪枝,从无限到有限>
题目传送 显然是道深搜题.由于蛋糕上表面在最底层的半径确认后就确认了,所以搜索时的面积着重看侧面积. 找维度/搜索面临状态/对象:当前体积v,当前外表面面积s,各层的半径r[],各层的高度h[]. 可 ...
- 模拟赛T5 : domino ——深搜+剪枝+位运算优化
这道题涉及的知识点有点多... 所以还是比较有意思的. domino 描述 迈克生日那天收到一张 N*N 的表格(1 ≤ N ≤ 2000),每个格子里有一个非 负整数(整数范围 0~1000),迈克 ...
随机推荐
- BZOJ 2730: [HNOI2012]矿场搭建( tarjan )
先tarjan求出割点.. 割点把图分成了几个双连通分量..只需dfs找出即可. 然后一个bcc有>2个割点, 那么这个bcc就不用建了, 因为一定可以走到其他救援出口. 只有一个割点的bcc就 ...
- Unbuntu 14.04 下chrome browser bookmark 显示中文乱码解决方案
来源:http://blog.csdn.net/loveaborn/article/details/29579787 网上有人给出这个问题的解决是通过修改文件/etc/fonts/conf.d/49- ...
- 计算ptd
因为公司的IC扫描sensor的频率常常和adapter中的noise频率重叠,导致IC接收到的数据出错.所以我们经常会用示波器看adapter的Noise,再用傅里叶变换找到相应应该回避的频段,包括 ...
- 【.Net基础拾遗】适配器模式(Adapter)与多态
今天晚上跟大家主要来讨论下适配器模式和多态,什么是适配器模式呢?先抛给大家一个问题:假设两个类Student和Teacher继承一个抽象基类Person,如何在不改动三类情况下实现多Student.T ...
- 基于springmvc的简单增删改查实现---中间使用到了bean validation
package com.kite.controller; import java.util.HashMap; import java.util.Map; import javax.validation ...
- 安装Tomcat指定JDK(转)
一.应用实例 一般情况下一台服务器只跑一个业务,那么就直接配置一套环境,设置好Java环境变量即可.某些时候一台服务器上会安装多个业务,而且各个业务需要的JDK版本各不相同,或者为了使业务独立开来,需 ...
- 引用 RAM和ROM和Flash ROM的区别
用 饿狼 的 RAM和ROM和Flash ROM的区别 RAM(Random Access Memory)的全名为随机存取记忆体,它相当于PC机上的移动存储,用来存储和保存数据的.它在任何时候都可以读 ...
- php unset 数组陷阱
我们删除一个array, unset($arr); 想删除某个元素 unsert($arr[i]) 一个陷阱是: unset() 函数允许删除数组中的某个键.但要注意数组将不会重建索引.如果需要删除后 ...
- shell脚本中每次读取文件的一行
写法一: #!/bin/bash while read linedo echo $line #这里可根据实际用途变化 done < file #需要读取的文件 ...
- 基于visual Studio2013解决算法导论之055拓扑排序
题目 拓扑排序 解决代码及点评 // 拓扑排序.cpp : 定义控制台应用程序的入口点. // // 深度优先.cpp : 定义控制台应用程序的入口点. // // 图的邻接表表示.cpp : ...