京東筆試題-鐳射炮(分析轉換簡化問題)
阿新 • • 發佈:2019-01-29
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; }