主题:智破连环阵!!~请高手哥哥们看一下。
duanfengo7
[专家分:0] 发布于 2005-08-06 21:10:00
智破连环阵
【问题描述】
B国在耗资百亿元之后终于研制出了新式武器——连环阵(Zenith Protected Linked Hybrid Zone),并声称这是一种无敌的自发性智能武器。但A国经侦察发现,连环阵其实是由M个独立武器组成的。这M个武器编号为1,2,…,M。每件武器有两种状态:无敌自卫状态和攻击状态。最初,1号武器处于攻击状态,其他武器都处在无敌自卫状态。以后,一旦第i(1 £ i<M)号武器被消灭,1秒钟以后第i+1号武器就自动从无敌自卫状态变成攻击状态。当第M号武器被消灭以后,这个造价昂贵的连环阵就被彻底摧毁了。
为了打败B国,A国军事部长打算用最廉价的武器——炸弹来消灭连环阵。经过长时间的精密探测,A国的军事家们掌握了连环阵中M个武器的平面坐标,然后依此选择了n个点,并在这些点上安放了特殊的定时炸弹。这n个炸弹编号为1,2,…,n。每个炸弹的作用半径均为k,且会持续爆炸5分钟。在这5分钟内,每枚炸弹都可以在瞬间消灭离它直线距离不超过k的、处在攻击状态的B国武器。和连环阵类似,最初a1号炸弹持续引爆5分钟时间,然后a2号炸弹持续引爆5分钟时间,接着a3号炸弹引爆……以此类推,直到连环阵被摧毁。在每个炸弹爆炸的时候,其它尚未引爆的炸弹都处于地下隐蔽处,不会被己方的炸弹摧毁。
显然,选好a1、a2、a3...十分重要。好的序列可以在仅使用较少炸弹的情况下就能将连环阵摧毁;坏的序列可能在使用完所有炸弹后仍无法将连环阵摧毁。现在,请你决定一个序列a1、a2、a3…使得在第ax号炸弹引爆的时间内连环阵被摧毁。这里的x应当尽量小。
【输入文件】
输入文件zplhz.in第一行包含三个整数:M、n和k(1 £ M, n£ 100,1£ k£ 1000),分别表示B国连环阵由M个武器组成,A国有n个炸弹可以使用,炸弹攻击范围为k。以下M行,每行由一对整数xi,yi(0£ xi,yi £ 10000)组成,表示第i(1£ i£ M)号武器的平面坐标。再接下来n行,每行由一对整数ui,vi(0 £ ui,vi£ 10000)组成,表示第i(1£ i£ n)号炸弹的平面坐标。输入数据保证无误和有解。
测试数据中的xi、yi、ui、vi是随机生成的。
【输出文件】
输出文件zplhz.out的第一行包含一个整数x,表示实际使用的炸弹数。第二行包括x个整数,依次表示a1,a2,…,ax。
【样例输入1】
4 3 6
0 6
6 6
6 0
0 0
1 5
0 3
1 1
【样例输出1】
2
1 3
【样例输入2】
10 10 45
41 67
34 0
69 24
78 58
62 64
5 45
81 27
61 91
95 42
27 36
91 4
2 53
92 82
21 16
18 95
47 26
71 38
69 12
67 99
35 94
【样例输出2】
5
6 2 1 3 4
请高手们帮帮忙,不求给给出全部代码,只要具体的算法就成,当然能给出全部的代码小弟弟求之不得了!~嘿!@~
回复列表 (共9个回复)
沙发
duanfengo7 [专家分:0] 发布于 2005-08-08 10:38:00
怎么都没有人回帖啊??
大家讨论一下撒,不一定要对的,把自己的想法思路说一下就可以了是撒。。
板凳
williamgood [专家分:330] 发布于 2005-10-13 22:15:00
能不能简化一下题目,我不喜欢看太多文字,拜托!!
3 楼
KID [专家分:820] 发布于 2005-10-14 12:18:00
@_@
4 楼
xuzhenyi [专家分:850] 发布于 2005-10-14 18:50:00
看的云里雾里~~~~~~~~
不会是动态规划吧 或者倒过来递推
不清楚
5 楼
michard9 [专家分:70] 发布于 2005-10-15 13:31:00
文字暴多……恶寒~~~~~~~~~~
看得晕阿~~~~~~~摆脱下次楼主大人多少把自己的想法大致理一下,这样就把一大串的文字扔出来很不人道阿`~~~~~~~~
按照题目上的意思,我觉得:
1。炸弹应该尽可能放在可以炸毁敌方最多武器数的地方,因为炸弹可持续爆炸五分钟(问题在于,上题中所说的持续引爆和持续爆炸有无异同?)而敌方武器被炸毁一次后二号炸弹转换状态时间为1秒,即在这1秒内其仍旧处于无敌自卫状态?炸弹引爆(就是想要它炸他就开炸?)不需时间?……
混乱了,最终感想就是那个B国首脑脑子被撞坏了阿~~~耗资百亿元之研制的连环阵(Zenith Protected Linked Hybrid Zone),竟然就是这种废渣……用炸弹竟然就可以摧毁,还让世间多了像这种样子变态的题目,去跳楼算了……
6 楼
lanxueyu [专家分:90] 发布于 2005-10-16 14:51:00
A国先选取一个能炸很多B国武器的炸弹,以这个炸弹为基准,在选择离这个炸弹最远同时炸B国连续武器最多的炸弹,在以此炸弹为基准这样选择下去就可以达到最少需求的目地.
7 楼
michard9 [专家分:70] 发布于 2005-10-16 22:37:00
楼上的说清楚一点好不好~~~~~~不明白也~~~~
8 楼
cusa [专家分:180] 发布于 2005-10-18 17:07:00
带个头,算法不是很好,就这个意思
#include <stdio.h>
#include <malloc.h>
#include <math.h>
typedef struct{
int x;
int y;
}Pos;
typedef struct{
int bb;
int id;
Pos p;
}Bomb;
typedef struct{
int dd;
int id;
Pos p;
}Weapon;
/* declare the function will be used */
int distance(Pos weapon,Pos bomb);
/*
main()
*/
int main(void)
{
char result[128];
int M,n,k;
int deadcnt = 0;
int dead = 0;
int temp = 0;
int i,j,cnt = 0;
int count = 0;
Weapon* weapon;
Bomb* bomb;
FILE* fp_out = (FILE*)NULL;
FILE* fp_in = (FILE*)NULL;
result[0] = '\0';
fp_in = fopen("zplhz.in","r");
fp_out = fopen("zplhz.out","w");
/* Set pointer to beginning of file: */
fseek( fp_in, 0L, SEEK_SET );
/* Read data from input file: */
fscanf( fp_in, "%d", &M );
fscanf( fp_in, "%d", &n );
fscanf( fp_in, "%d", &k );
weapon = (Weapon *)malloc(M*sizeof(Weapon));
bomb = (Bomb *)malloc(n*sizeof(Bomb));
for( i = 0;i < M;i++ ) {
weapon[i].dd = 0;
fscanf( fp_in, "%d", &weapon[i].p.x );
fscanf( fp_in, "%d", &weapon[i].p.y );
}
for( i = 0;i < n;i++ ) {
bomb[i].bb = 0;
fscanf( fp_in, "%d", &bomb[i].p.x );
fscanf( fp_in, "%d", &bomb[i].p.y );
}
/* Start */
cnt = 0;
LOOP:
temp = 0;
for( i = 0;i < n;i++ ) {
dead = 0;
if(bomb[i].bb == 1) continue;
for( j = deadcnt;j < M;j++ ) {
if( distance(bomb[i].p,weapon[j].p)<=k*k ) {
dead++;
}
else break;
}
if( dead>temp ) {
cnt = i;
temp = dead;
}
}
bomb[cnt].bb = 1;
deadcnt = deadcnt+temp;
count++;
sprintf(result,"%s %d",result,cnt+1);
if(deadcnt != M) goto LOOP;
/* End */
fprintf(fp_out,"%d\n%s",count,result);
fclose(fp_in);
fclose(fp_out);
printf("result saved in file 'zplhz.out'\n");
}
/*
distance()
*/
int distance(Pos A,Pos B)
{
int X,Y;
X = A.x-B.x;
Y = A.y-B.y;
return( X*X+Y*Y );
}
9 楼
我是大绵羊 [专家分:0] 发布于 2007-05-15 18:43:00
初步分析:
A国炸弹I可以炸到B国武器J的条件: (u[i]-x[j])2+(v[i]-y[j])2<=r2
结论:很难找到求最优解的多项式算法。
面对此类问题,一般只有搜索策略。
进一步分析:
每一颗炸弹必定炸掉B国武器中编号连续的一段。
5分钟只是表明每一颗炸弹可以炸掉任意多个编号连续的B国武器。
部分搜索:
此题使用部分搜索的算法需要一些转化:如果已经将B国武器根据编号分为x
段,[Si,Ti] (S1=1,Ti>=Si,Ti+1=Si+1)。然后判断是否可以从A国的N颗炸弹中选出x
颗,分别可以炸掉其中的一段。
其实我们把搜索分为了两部分,先通过搜索将B国武器根据编号分为x段,再
通过搜索判断是否可以从A国的N颗炸弹中选出x颗,分别可以炸掉其中的一段。
其实第二部分可以用匹配来解决。
C[S][T][I] 表示A国炸弹I是否可以炸到B国武器S,S+1..T-1,T。
C[S][S][I]=((u[I]-x[S])2+(v[I]-y[S])2<=R2)
C[S][T][I]=C[S][T-1][I] & C[T][T][I] (S<T)
求C的时间复杂度为O(N3)。
建图:左边x个点,表示B国武器根据编号分为的x段,右边N个点,表示A国
的N颗炸弹。左边第i个点到右边第j个点有边的条件即:C[Si][Ti][j]。
搜索的任务就是将B国武器根据编号划分为若干段+二分图匹配判断。
性能分析(1):
搜索的基本框架已经建立,虽然数据是随机生成的,但是M个B国武器的划分
方案还是非常多的,有时可能高达2m。时间上很难承受,如果使用卡时,正确性
受到影响,效果不会很好。
只有4个数据可以在时限内出解,另外6个如果卡时,有1个也可以得到最优
解。
优化:
优化可以通过可行性和最优性两方面分析。
优化一(最优性):如果A国炸弹可以重复使用,设:
Dist[i]=炸掉B国武器i-m的最少使用炸弹数。可以用动态规划计算Dist值,
状态转移方程如下:
Dist[m+1]=0。
Dist[i]=Min(Dist[j]+1 | Can[i][j-1][k](1<=k<=n)) (1<=i<=n)
(i<j<=n+1)
求Dist的时间复杂度为O(N3)。
从而产生了一个最优性剪枝条件:
if 当前已经使用的炸弹数+Dist[当前已经炸掉的B国武器数+1]>=当前找到
的最优解 then 剪枝;
优化二(可行性):
此搜索方法一般都可以用两个效果很好的可行性优化:
(1)提前判断是否可以匹配成功,避免多余的搜索。
(2)每次匹配可以从以前的匹配开始扩展,不需要重新开始。
如果当前的划分方法已经无法匹配成功,就没有搜索下去的必要了,只要每
搜索新的一段时立即通过匹配判断即可。
每次求匹配只要从原来的基础上扩展就可以了。
通过上述两个优化,程序的效率有了很大的提高。
性能分析(2):
虽然通过上述两个优化,程序的效率较原来的搜索有了很大的提高。10个测
试数据中有8个可以在时限内出解,另外2个如果卡时,有1个也可以得到最优解。
进一步优化:
优化二虽然排除了许多不必要的划分,但是在判断时浪费了不少时间。
因此,在枚举划分长度时,可以通过以前的划分和匹配情况(被匹配的边),
用O(n2)的时间复杂度的宽度优先搜索计算出下一个划分的最大长度maxL,显然
下一个划分的长度在[1,maxL]都一定可以找到可行的匹配。这样既节省了判断
的时间,又可以使每次划分长度从长到短枚举,使程序尽快逼近最优解,同时增
强了剪枝条件一的效果。
这一部分的实现,首先需要求MaxT。
MaxT[I][S]=炸弹i,从S开始炸,可以炸到的最大编号。
如果,炸弹i炸不到S,则MaxT[I][S]=S-1。
求MaxT[I][S]可以用动态规划的方法解决。状态转移方程为:
MaxT[I][S]= 炸弹i炸不到S S-1
炸弹i炸得到S MaxT[i][S+1]
MaxT[i][m+1]=m
求MaxT的时间复杂度为O(N2)。
具体实现方法,考虑二分图右边的n个结点(n颗炸弹),如果结点i没有匹配,
i被认为可以使用。对于一个已经匹配的结点i,如果从任何一个没有匹配的结点
出发存在一条到达i,而且i为外点的交错路,i也被认为可以使用。
计算所有从没有匹配点出发的交错路(没有匹配点i出发的交错路没有被匹
配点i一定为外点)所能到达的匹配的结点,只要从每一个没有匹配的结点出发,
宽度优先搜索,只要O(N2)的时间。注意判断重复(如果一个已经匹配的结点已
经被确定为可以使用,那么不需要对它再扩展一次,因为当把这个已经匹配的结
点确定为可以使用的结点的时候,已经从这个结点扩展过,如果再扩展必将产生
无谓的重复)
所以MaxL=Max(MaxT[I][S] | i可以使用);
性能分析(3):
通过以上的优化,所有数据都是瞬间出解,并且所有结果都是最优解。
甚至对n=200的随机数据,也可以在瞬间出解,可见程序的效率有了很大的
提高。
精益求精:
另外,还有两个优化,但是有时效果不好,但也值得一提。
优化三:分支定界。这样可以增强剪枝条件一的效果,但是当最优解与
Dist[1]相差比较远的时候,会浪费一定的时间。
优化四:优化一中Dist[i]的值有时并不是最优的,通过测试,发现如果
Dist[i]的值与最优值相差1,特别是当i 小的时候,程序的速度都会有明显的
影响。所以,可以通过同样的搜索来计算Dist[i],(本题的答案就是Dist[1])。
这样做可以增强剪枝条件一的效果,但是同时对每个i都要搜索也浪费了一定的
时间。
程序结果比较:
1 2 3 4 5 6 7 8 9 10
最简单的
搜索
0.00 0.00 0.50
Time
Over
0.65
Time
Over
Time
Over
Time
Over
Time
Over
Time
Over
优化的搜
索
0.01 0.01 0.10
Time
Over
0.50 0.80
Time
Over
0.55 0.30 0.80
进一步优
化的搜索
0.01 0.01 0.02 0.03 0.00 0.02 0.02 0.01 0.02 0.02
此搜索方法一般都可以用两个效果很好的可行性优化:
(1)提前判断是否可以成功,避免多余的搜索。
(2)每次判断尽量多利用以前的判断结果。
我来回复