题目:
Telephone poles are part of an outdated technology. Cell phones nowadays allow us to call whoever we want, wherever we want, independent of any wire. There is one problem - without a service tower nearby a cell phone is useless. In the absence of hills and mountains, a service tower will provide coverage for a circular area. Instead of planning where to place the wires, a wireless telephone company has to plan where to build its service towers. Building the towers too far apart causes holes in the coverage and increases complaints. Building the towers too close to each other results in large areas covered by more than one service tower, which is redundant and inefficient. International Cell Phone Company is developing a network strategy to determine the optimal placement of service towers. Since most customers have replaced their old wired home phones by cell phones, the strategy for planning service towers is therefore to cover as many homes of customers as possible. The figure below shows the service areas for the five towers ICPC’s strategic department planned to build this year. Tower 5 will serve 24 customers, 6 of which are also served by tower 4. Towers 1, 2 and 3 have a common service area containing 3 customers.
Shortly after the plans for these five towers had been published, higher management issued a stop on all tower building. Protesting customers forced them to weaken this decree, and allow the building of three towers out of the five planned. These three towers should serve as many customers as possible, of course. Finding the best possible choice for the towers to build is not trivial (the best choice in this case is towers 2, 4 and 5, serving 68 customers).
You must write a program to help ICPC choose which towers to build in cases like these. If several choices of towers serve the same number of customers, choices including tower 1 are preferable. If this rule still leaves room for more than one solution, solutions including tower 2 are preferable, and so on.
Input The input file contains several test cases. The first line of each test case contains two positive integers: the number n (n ≤ 20) of towers planned, and the number of towers to be actually built. The next line contains n numbers, each giving the number of customers served by a planned tower. (The first number refers to the first tower, and so on.) No tower serves more than a million people. The next line contains the number m (m ≤ 10) of common service areas. Each of the next m lines contains the description of a common service area. Such a line starts with the number t (t > 1) of towers for which this is a common service area, followed by the t numbers of the towers. The last number on the line is the number of customers in the common service area. The last line of the input file consists of the two integers ‘0 0’.
Output For each test case, display the number of customers served and the best choice for the location of the towers. Follow the format of the sample output. Print a blank line after each test case.
Sample Input
1:
5 3
15 20 25 30 24
5
2 1 2 7
3 1 2 3 3
2 2 3 2
2 3 4 5
2 4 5 6
2:
5 3
25 25 25 25 25
4
2 1 2 5
2 2 3 5
2 3 4 5
2 4 5 5
5 3
25 25 25 25 25
0
0 0
Sample Output
Case Number 1
Number of Customers: 68
Locations recommended: 2 4 5

Case Number 2
Number of Customers: 75
Locations recommended: 1 3 5
Case Number 3 Number of Customers: 75
Locations recommended: 1 2 3

翻译

电线杆是过时技术的一部分。现在的手机让我们可以打电话给任何人,无论我们想要什么,我们都希望独立于任何电线。有一个问题 - 没有服务塔附近的手机没用。在没有丘陵和山脉的情况下,服务塔将为圆形区域提供覆盖。无线电话公司不必计划在哪里放置电线,而是必须规划到哪里建立服务塔。将塔建造得相距太远会导致覆盖范围内出现漏洞并增加投诉。建造塔彼此太靠近会导致大面积被多个区域覆盖服务塔,这是多余和低效的。国际手机公司正在制定网络战略以确定最佳位置服务塔。由于大多数客户已经用手机取代旧的有线家用电话,因此,规划服务塔的策略是尽可能多地覆盖客户的家。下图显示了ICPC战略部门计划的五座塔楼的服务区域,建立今年。 5号塔将为24个客户提供服务,其中6个也由4号塔服务。塔1,2和3有一个包含3个客户的公共服务区。

在这五座塔楼的计划发布后不久,高层管理人员发出了停顿

在所有塔楼。 抗议客户迫使他们削弱这项法令,并允许建筑物

计划中的五个塔中的三个塔。 这三座塔应该尽可能多地为客户服务,当然。 找到建造塔楼的最佳选择并非易事(这是最佳选择)案例是塔2,4和5,为68个客户提供服务)。

您必须编写一个程序来帮助ICPC选择在这种情况下构建哪些塔。 如果好几个塔的选择服务于相同数量的客户,包括塔1在内的选择是优选的。 如果这规则仍然留有多个解决方案的空间,包括塔2的解决方案是优选的,等等。

stl电线杆思路与思考_状压dp


输入

输入文件包含几个测试用例。每个测试用例的第一行包含两个正整数:计划的塔数n(n≤20),以及实际建造的塔数。下一个

行包含n个数字,每个数字给出计划塔楼服务的客户数量。 (首先数字指的是第一座塔,依此类推。)没有一座塔供超过一百万人使用。下一个行包含公共服务区域的数量m(m≤10)。接下来的m行中的每一行都包含公共服务区域的描述。这样的一条线以塔的数量t,这是一个常见的服务区域,其次是t个塔楼。该行的最后一个数字是公共服务区域内的客户数量。输入文件的最后一行包含两行

整数’0 0’。

输出

对于每个测试用例,显示所服务的客户数量以及最佳位置选择

塔。遵循示例输出的格式。在每个测试用例后打印一个空行。

题解:
这道题涉及到了状态压缩dp,dp我们没有学习,更不要说状压dp了,状压dp 就是利用位运算去表示 都是在二进制的基础上进行的,每一种二进制表示一种状态,比如说100000表示一个状态 然后1000001表示另一种状态,这道题如果能把题意读懂然后再了解状压dp去套模板是可以解决的。

这道题是寒假做的,因为是第一道,然后寒假时间也多,看了一上午没思路,然后下午我哥哥给我把题讲了一下,然后让我自己看书,给了我一个模板,最后给我改了一下,最后过了也没管,今天再去看发现很多地方都不懂,有把书看了一遍,现在总结一下。

状压dp是由旅行商和N皇后问题得出
旅行商问题(Traveling Salesman Problem,TSP)是旅行商要到若干个城市旅行,各城市之间的费用是已知的,为了节省费用,旅行商决定从所在城市出发,到每个城市旅行一次后返回初始城市,问他应选择什么样的路线才能使所走的总费用最短?此问题可描述如下:设G=(V,E)是一个具有边成本cij的有向图,cij的定义如下,对于所有的i和j,cij>0,若<i,j>不属于E,则cij=∞令|V|=n,并假设n>1。 G的一条周游路线是包含V中每个结点的一个有向环,周游路线的成本是此路线上所有边的成本和。
当一个状态是由上一状态得来的,我们可以用一般的dp来写,但当现在的状态是由多个状态得来的,那该怎么办。这个时候就应该用状压。一般用二进制数来表示哪些情况是成立,哪些不成立(也可能是三进制,四进制)。状压dp类型有很多,一般会与其他算法结合。
提到状压dp必须总结一下位运算,或运算了。
与运算
and运算通常用于二进制的取位操作,例如一个数 and 1的结果就是取二进制的最末位。这可以用来判断一个整数的奇偶,二进制的最末位为0表示该数为偶数,最末位为1表示该数为奇数。
相同位的两个数字都为1,则为1;若有一个不为1,则为0。
00101
&
11100
00100
或运算
or运算通常用于二进制特定位上的无条件赋值,例如一个数or 1的结果就是把二进制最末位强行变成1。如果需要把二进制最末位变成0,对这个数or 1之后再减一就可以了,其实际意义就是把这个数强行变成最接近的偶数。
相同位只要一个为1即为1
00101
|
11100
11101
还有一个左移运算符<< ,例如1<<n == 2^n

异或运算
异或的符号是^。按位异或运算, 对等长二进制模式按位或二进制数的每一位执行逻辑按位异或操作. 操作的结果是如果某位不同则该位为1, 否则该位为0.xor运算的逆运算是它本身,也就是说两次异或同一个数最后结果不变,即(a xor b) xor b = a。相同位不同则为1,相同则为0。
判断数字x第i位是否为1,if(x&(1<<i))
将一个数字x第i位改成1,x|=(1<<i)
伪代码如下
1,记忆化搜索
我们可以将下标为集合的编码成一个整数,或者利用中序二叉树存储;我们采用的方法是将每一个元素的选取对应到一个二进制位中去!!

//输入
int dp[1<<maxn][maxn];//记忆化搜索用的数组
int solve(int S,int v){
if(dp[S][v]>=0){
return dp[S][v];
}
if(S==(1<<n)-1&&v==0){//已经访问过所有节点并回到0号节点
return dp[S][v]=0;
}
int minn=INF;
for(int u=0;u<n;u++){
if(!S>>u&1){//下一步移动到顶点u
minn=min(minn,solve(S|1<<u,u)+d[v][u]);
}
}
return dp[S][v]=minn;
}

复杂度为O((2n)*(n2))。
2,循环dp

#include<cstdio>
#include<iostream>
using namespace std;
int n,INF=1e9;
int dp[1<<10001][10001],d[10001][10001];
int main(){
cin>>n;
for(int S=0;S<1<<n;S++){
fill(dp[S],dp[S]+n,INF);
}
dp[(1<<n)-1][0]=0;
for(int S=(1<<n)-2;S>=0;S--){
for(int v=0;v<n;v++){
for(int u=0;u<n;u++){
if(!(S>>u&1)){
dp[S][v]=min(dp[S][v],dp[S|1<<u][u]+d[v][u]);
}
}
}
}
cout<<dp[0][0];
}

像这种dp就成为状压dp,现在看的话还是很不理解,就先记录下来,然后以后慢慢学习思考。