1. 程式人生 > >京東筆試題-鐳射炮(分析轉換簡化問題)

京東筆試題-鐳射炮(分析轉換簡化問題)

http://exercise.acmcoder.com/online/online_judge_ques?ques_id=4401&konwledgeId=41

收到情報,有批新造的機器人要運輸到前線。小C將去破壞機器人的運輸。小C將鐳射炮放置在公路的一旁,等運輸車經過的時候發射(假設鐳射炮一定可以射穿車輛)。由於能源有限,鐳射炮只能發射兩次。可以認為鐳射炮放在座標軸的原點處,並向y軸正方向發射。每輛運輸車可以看作是一個矩形,起始的x軸座標為Xi ,所有的車均位於第一象限,長度為Li,速度為1,朝x軸負方向運動。即經過t時間後,該車車頭的x座標為Xi-t,車尾座標為Xi-t+Li 。只要打中車的任何一個部分就算擊中。

請你算算,他在哪兩個時刻發射,才能摧毀最多的運輸車。

解析:

       假設矩形(車輛位置不變),兩個鐳射炮在動,分析出“兩個鐳射炮能打最多的車的位置,一定等價於在某個矩形框的最左邊位置”是轉化問題的關鍵。但摧毀最多運輸車的情況下,兩個發射時刻的位置不是唯一的,這也是題目的漏洞所在。故只需遍歷所有任意組合的兩個矩形框,然後再去遍歷哪些車能被打到,複雜度為o(n3).

     困擾我的地方是,這兩個鐳射炮可能打到的是同一輛車,故要排除重複的情況。所以就有人說,先遍歷一遍,儲存打到的矩形車數目,然後把這些車給剔除掉,然後在遍歷一遍,得到另外一個數組,然後將兩個陣列相加,得到最大值。這樣會需要o(n2)的記憶體空間。方案上是可行的。但還是要挖掘出鐳射炮的位置一定等價於在矩形框的最左側位置。

    當然在最右側位置也是對的。

#include<cstdio>
#include<cstring>

int a[205], b[205], c[205];
bool canShoot(int w, int e){//鐳射炮在第w個矩形框的最左邊能否打到第e個車
	return a[e] <= a[w] && b[e] >= a[w];
}
int n;
int getShootNumber(int w, int e){
	int re = 0;
	for (int i = 1; i <= n; i++)//遍歷所有的矩形車,看是否能被w,e位置處的鐳射炮其中之一打到
		if (canShoot(w, i) || canShoot(e, i))re++;
	return re;
}
void work(){
	scanf("%d", &n);
	for (int i = 1; i <= n; i++){
		int l;
		scanf("%d %d", &a[i], &l);
		b[i] = a[i] + l;
	}
	int ans = 0;
	for (int i = 1; i <= n; i++)
		for (int j = i + 1; j <= n; j++){
			int k = getShootNumber(i, j);
			if (k>ans)ans = k;
		}
	printf("%d\n", ans);
}
int main(){
	work();
	return 0;
}