在正文之前先说点题外话。
寒假以来,由于自身的种种原因,我在OI方面没有用功,既没有刷题也没有进行总结,甚至连题库和博客都没有登录过,在此要认真检讨。而且今天的创新班也让我发现自己开始出现的一些弊病:心态方面,方法和习惯等等。为什么自己开始出现这些问题?如何解决?还是要靠良好的心态为基础。希望新的学期里戒骄戒躁,坚持刷题和写博客,日积月累慢慢进步。毕竟身边厉害的同学和学长很多,自己没有任何借口来偷懒,没有任何理由来骄傲。
=============
【试题来源】
USACO月赛2016年1月铜牌组
【题目描述】
牛奶Bessie设计了一个游戏:“愤怒的牛奶”。游戏的原型是:有一些可爆燃的草堆分布在一条数轴的不同坐标,玩家用弹弓把一头奶牛发射到数轴上。牛奶砸到草堆上的冲击能量会引发草堆燃爆,并有可能引起附近的草堆连环燃爆。游戏的目标是玩家用一头奶牛燃爆尽可能多的草堆。
有N个草堆在数轴的不同位置,坐标为x1,x2,….,xn。如果玩家把牛发射到坐标是x的草堆上,这个草堆就会燃爆,冲击波的半径是1,距离它是1的草堆也会被燃爆。这些相邻的草堆会同时燃爆,并且冲击波的半径是2。下一步,被燃爆的草堆冲击波半径会是3。一般的,时间t燃爆的草堆,每一个的冲击波半径是t,被这些冲击波引爆的草堆在t+1时刻会产生冲击波半径是t+1,以此类推。
请计算,只用一头奶牛玩家最多可以燃爆多少草堆?
【输入格式】
第一行:一个整数N( 1 ≤ N ≤ 100)。
下面有N行,每行一个整数:x1, x2 ,…,xn,范围在[0…1,000,000,000]
【输出格式】
输出最大可能燃爆的草堆数。
【输入样例】
6
8
5
6
13
3
4
【输出样例】
5
【样例解释】
In this example, launching a cow onto the hay bale at position 5 will cause the bales at positions 4 and 6 to explode, each with blast radius 2. These explosions in turn cause the bales at positions 3 and 8 to explode, each with blast radius 3. However, these final explosions are not strong enough to reach the bale at position 13.
=============
看到这题,容易想到几种不同的算法,各自实现起来会有不同的特点。
而且我们还发现,本题数据范围很小,完全可以用朴素的方法实现,例如模拟。
(挺符合铜牌组题目的特点。。)
那么其实我的这种方法是非常麻烦,相当笨的。#include<cstdlib>
#include<cstdio>
#include<cstring>
//定义max和min宏
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
const int SIZE = 100 + 5 ;
int N , x[SIZE] , ans=0 , f[SIZE] ;
int work ( int ) ;//work(n)表示以n为发射点最多可以燃爆多少草堆
int main () {//输入数据
scanf ( "%d" , &N ) ;
for ( int i=0 ; i!=N ; ++i )
scanf ( "%d" , &x[i] ) ;//枚举发射点,取最优解
for ( int i=0 ; i!=N ; ++i )
ans = max ( ans , work(i) ) ;
printf ( "%d\n" , ans ) ;
return 0 ;
}
int work ( int cur ) {//f[]数组储存坐标为xi的草堆被燃爆的时间
memset ( f , -1 , sizeof f ) ; //-1表示草堆未被燃爆
f[cur] = 0 ; //选定的发射点是初始燃爆点,记作时间0
int tot=1 ; //当前被燃爆的草堆数量
for ( int t=1 ; t!=N+1 ; ++t ) { //t为当前时间
bool flag=false ; //flag表示当前时刻是否有新草堆被燃爆
for ( int i=0 ; i!=N ; ++i ) //枚举每一个草堆
if ( f[i]==-1 ) //若草堆i未被燃爆,尝试燃爆它
for ( int j=0 ; j!=N ; ++j )//枚举一个可以燃爆它的草堆
if ( f[j]==t-1 && abs(x[i]-x[j])<=t ) {//若草堆j是前一个时间点燃爆的且半径足够
f[i] = t ; //在时间t燃爆草堆i
++ tot ; //统计总数
flag = true ;//标记有草堆被燃爆break ; //停止寻找可以燃爆i的j
}
if (!flag) return tot ;//当前时间没有燃爆任何草堆,则继续进行无意义,
//tot即为以cur为初始发射点的最多燃爆数,返回它
}
return tot ; //所有草堆均被燃爆的情况
}