代码源每日一题-宝箱(贪心/思维)
題目鏈接:寶箱 - 題目 - Daimayuan Online Judge
原題鏈接:C - Gacha (atcoder.jp)(沒英文題面哇。。。)
大致題意:?坐標軸上有??個鑰匙和? 個寶箱, 玩家初始位置為?, 每一步可以走到? 或者?.
當玩家到達一個有鑰匙的位置時, 他可以將鑰匙撿起. 當玩家到達一個有寶箱的位置時, 他可以選擇使用一個鑰匙將寶箱打開.
試求出玩家最少需要走多少步才能打開所有寶箱.
注: 同一個位置可以同時出現(xiàn)寶箱和鑰匙, 但同一位置不會出現(xiàn)超過一個寶箱或超過一個鑰匙.
題解:我們可以發(fā)現(xiàn),最終一定會在某一個寶箱的位置停下來,所以我們來枚舉所有寶箱,取他們的最小值。假定寶箱與鑰匙的最大位置為 ,我們在第??個寶箱停下來,那么意味著在當前位置結(jié)束的答案為??,首先從??走到最大點,再往回走走到當前點?。這樣需要走的路程為??。因為往回走到??停止了,我們發(fā)現(xiàn)前?個寶箱會出現(xiàn)未打開的情況。那么假定??就代表要保證前??個寶箱開啟需要額外走的最短路程。這樣就可以保證往回走到??結(jié)束時,且前面的所有寶箱都打開了。那么??怎么求,是本題關(guān)鍵。?
我們可以發(fā)現(xiàn),若?,那么走到當前點無需走額外的距離就可以打開寶箱,否則? 肯定需要外走一些距離。我們當前的位置是?,能開啟這個寶箱的鑰匙在?,那么當前存在兩種可能 :
????????1.從當前 ?出發(fā)去拿鑰匙再回來開,需要的額外路程為??
? ? ? ? 2.若有存在鑰匙的位置??并且?,那么意味著這把鑰匙一定屬于當前這個寶箱之前的某一個寶箱,那么只要在拿取那個寶箱鑰匙的時候“順帶”拿上當前這把鑰匙,這樣額外花費的路程為?,這個路程一定小于?。
所以我們只需要記錄一下當前拿的鑰匙的最大位置(當然若鑰匙位置小于寶箱則無需記錄,因為這樣不會有額外走的路程),每次遇到一個寶箱無法打開,判斷一下這把鑰匙是直接拿路程短還是在拿上一把鑰匙是“順帶”拿路程短,就可以求出 ?,即要保證前??個寶箱開啟需要額外走的最短路程。
#include <bits/stdc++.h>using namespace std;#define int long longsigned main() {int n, res = 2e14, s = 0; cin >> n; //s 代表需要額外走的路vector<int> a(n + 1), k(n + 1);for(int i=1; i<=n; i++) cin >> a[i];for(int i=1; i<=n; i++) cin >> k[i]; int mx = max(k[n], a[n]);int last = -1;for(int i=1; i<=n; i++) {if(a[i] < k[i]) { //如果當前這個寶箱無法被鑰匙打開res = min(res, s + 2 * mx - a[i]); //以當前點為結(jié)束點,這意味著前i-1個點都無需走回去,s代表的就是開前i-1個寶箱需要額外走的距離s += (k[i] - max(a[i], last)) * 2; //更新 s last = k[i]; } else res = res = min(res, s + 2 * mx - a[i]);}cout << res << '\n'; }總結(jié)
以上是生活随笔為你收集整理的代码源每日一题-宝箱(贪心/思维)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA 计算宝箱概率问题
- 下一篇: 精华来了(含PPT) | 淘系技术嘉年华