$ \Large\texttt{預估/實際分數:200/200}$html
題目描述 |
---|
Wexley最近發現了一個古老的屏幕遊戲。遊戲的屏幕被劃分紅n列。 在屏幕的底端,有一個寬爲m列的籃子(m<n)。 在遊戲過程當中,Wexley能左右移動這個籃子, Wexley的操做很犀利,移動是瞬間完成的,可是籃子必須始終都在屏幕中。 蘋果從屏幕的頂端落下,每一個蘋果從n列中的某一列頂端掉落, 垂直掉落到屏幕的底端。每一個蘋果老是在上一個蘋果掉落到底端的時候開始掉落。 Wexley想要經過移動籃子來接住全部的蘋果。起先,籃子在屏幕的最左端。 求出Wexley要接住全部的蘋果所需移動的最短距離。
輸入 |
---|
第一行,兩個整數n、m,如題所述 第二行,一個整數k,表示掉落的蘋果總數 接下來k行,每行一個整數Ai,表示每一個蘋果掉落的位置
輸出 |
---|
一行一個整數,表示所需移動最短距離
樣例輸入 |
---|
Sample Input1: 5 1 3 1 5 3 Sample Input2: 5 2 3 1 5 3
樣例輸出 |
---|
Sample Output1: 6 Sample Output2: 4
本題的算法是模擬。node
假設籃子的左邊的位置是\(x\), 蘋果的位置是\(y\)算法
若是蘋果在籃子右邊就只要走\(y - x - (m - 1)\)步,
若是蘋果在籃子左邊就要走\(x - y\)步。數組
籃子的位置再隨着移動就行了。學習
for (int i = 1; i <= k; i++) { scanf ("%d", &y); if (y >= x && y <= x + m - 1) continue; if (x < y) { ans += y - x - (m - 1); x = y - m + 1; } else { ans += x - y; x = y; } }
題目描述 |
---|
Leo是一個快樂的火星人,老是能和地球上的OIers玩得很high。 2012到了,Leo又被召回火星了,在火星上沒人陪他玩了, 可是他有好多好多積木,因而他開始搭積木玩。 火星人能製造n種積木,積木能無限供應。每種積木都是長方體,第i種積木的長、寬、高分別爲li、wi、hi。 積木能夠旋轉,使得長寬高任意變換。Leo想要用這些積木搭一個最高的塔。問題是, 若是要把一個積木放在另外一個積木上面, 必須保證上面積木的長和寬都嚴格小於下面積木的長和寬。這意味着, 即便兩塊長寬相同的積木也不能堆起來。 火星上沒有電腦,好心的你決定幫助Leo求出最高的塔的高度。 【提示】 每種積木均可以拆分紅高度分別爲li、wi、hi的三種積木,另兩邊做爲長和寬,保證長>=寬。
輸入 |
---|
第一行,一個整數n,表示積木的種數 接下來n行,每行3個整數li,wi,hi,表示積木的長寬高
輸出 |
---|
一行一個整數,表示塔高的最大值
樣例輸入 |
---|
Sample Input1: 1 10 20 30 Sample Input2: 2 6 8 10 5 5 5 Sample Input3: 5 31 41 59 26 53 58 97 93 23 84 62 64 33 83 27
樣例輸出 |
---|
Sample Output1: 40 Sample Output2: 21 Sample Output3: 342
本題的算法是動態規劃。優化
首先,由於它的長、寬、高能夠任意位置,因此把每個合理(即長$\geq $寬) 記錄下來,每個積木就會有\(3\)種方案,排個序。spa
設\(F_i\)表示第\(i\)個積木放了的話,塔的高度,那麼動態轉移方程就能推出來了code
bool cmp(node a, node b) //排寬 { return a.w > b.w; } bool cmp2(node a, node b) //排長 { return a.h > b.h; }
for (int i = 1; i <= n; i++) //記錄方案與讀入 { int l, w, h; scanf ("%d%d%d", &l, &w, &h); if (w <= h)a[++m].l = l, a[m].w = w, a[m].h = h; if (h <= w)a[++m].l = l, a[m].w = h, a[m].h = w; if (l <= w)a[++m].l = h, a[m].w = l, a[m].h = w; if (w <= l)a[++m].l = h, a[m].w = w, a[m].h = l; if (l <= h)a[++m].l = w, a[m].w = l, a[m].h = h; if (h <= l)a[++m].l = w, a[m].w = h, a[m].h = l; } sort(a + 1, a + 1 + m, cmp); for (int i = 1, begin = 1; i <= m; i++) //排序(方法可能很獨特...) { if(a[i].w != a[i + 1].w) { sort(a + begin, a + 1 + i, cmp2); begin = i + 1; } } a[0].h = 2147483646; //DP a[0].w = 2147483646; f[1] = a[1].l; for (int i = 2; i <= m; i++) { for (int j = i - 1; j >= 0; j--) { if (!(a[i].h < a[j].h && a[i].w < a[j].w)) continue; f[i] = max(f[i], f[j] + a[i].l); } } for (int i = 2; i <= m; i++) ans = max(ans, f[i]); printf("%lld", ans);
題目描述 |
---|
Treeland是一個有n個城市組成的國家,其中一些城市之間有單向邊連通。在這個國家中一共有n-1條路。 咱們知道,若是咱們不考慮路的方向,那麼我能夠從任意城市到達任意城市。 最近,Treeland的總理Candy爲了發展經濟,想要從這n個城市中選擇一個做爲Treeland的首都, 首都必需要能到達其餘任意城市,這使得有些道路必須反向, 付出的代價即須要反向的道路條數。 Candy想要選擇一個城市做爲首都,使得付出的代價最小。 可能有多個城市知足條件,按編號從小到大輸出。
輸入 |
---|
第一行,一個整數n,表示城市個數 接下來n-1行,每行兩個整數x、y,表示城市x到城市y之間有一條單向路徑
輸出 |
---|
第一行,一個整數k,花費的最小代價。 第二行若干個整數,中間用空格隔開,表示知足條件的城市編號。行末沒有多餘的空格。
樣例輸入 |
---|
Sample Input1: 3 2 1 2 3 Sample Input2: 4 1 4 2 4 3 4
樣例輸出 |
---|
Sample Output1: 0 2 Sample Output2: 2 1 2 3
本題的算法是搜索(樹形,有點像樹形DP)。htm
可惡啊,\(\texttt{C++}\)作這題就錯了(\(\texttt{90}\)分)緣由是棧溢出,\(\texttt{Pascal}\)就對了TAT。。。blog
存樹時仍是按雙向邊來存,若是是出度那就是\(1\),若是是入度那就是\(0\)(代碼中有存儲方式)。
而後呢???
咱們用一個數組\(sx\)(名字是瞎取的)來存下以\(x\)爲根節點的樹,有多少個入度,這也將會是最終的答案。
咱們就是來求這個\(sx\)的。
怎麼求呢?
咱們能夠從根搜到葉子,記錄每個節點的入度(\(\texttt{for}\)一遍兒子節點),再退回給本身的父親。
你覺得這就結束了???
這只是求出了根節點的值!
怎麼求兒子呢?
這裏有一條性質:
當前節點\(x\)的一個兒子\(y\),若是是\(x\)指向\(y\),那\(sx_y=sx_x+1\)。不然\(sx_y=sx_x-1\)。
你們能夠根據下圖模擬一下。
先拿節點\(1\)來講咱們從求根節點的時候就已經知道了\(sx_1=1\)。
而後是節點\(2\),根據上面說的能夠知道\(sx_2=sx_1-1\)也就是\(sx_2=1-1=0\)確實沒錯。
而後是節點\(3\),根據上面說的能夠知道\(sx_3=sx_1+1\)也就是\(sx_3=1+1=2\)確實也沒錯(\(2\Rightarrow 1,1\Rightarrow 3\))。
。。。
**聲明:下面的prework實際上是某大佬和某教授讓我加的(是寫\(\texttt{C++}\)的時候加的,結果這個優化毫無*用)**
var minn, end1, x, y, i, j, n, tot : longint; head, sx, fa : array[1..200010]of longint; next, to1, qz : array[1..400010]of longint; procedure add1(x, y, op : longint); begin inc(tot); to1[tot] := y; qz[tot] := op; next[tot] := head[x]; head[x] := tot; end; procedure prework(x : longint); var y, i : longint; begin i := head[x]; while(i >= 1) do begin y := to1[i]; if(fa[x] = y)then begin i := next[i]; continue end; fa[y] := x; prework(y); i := next[i]; end; exit(); end; procedure init(x : longint); var i, y : longint; begin i := head[x]; while(i > 0) do begin y := to1[i]; if(fa[x] = y)then begin i := next[i]; continue end; if(y = 0) then break; init(y); inc(sx[x], sx[y]); if(qz[i] = 0)then inc(sx[x]) else inc(sx[y]); i := next[i]; end; end; procedure repeat1(x : longint); var i, y : longint; begin i := head[x]; while(i > 0) do begin y := to1[i]; if(fa[x] = y)then begin i := next[i]; continue end; if(y = 0) then break; sx[y] := sx[x]; if(qz[i] = 0)then dec(sx[y]) else inc(sx[y]); i := next[i]; repeat1(y); end; end; begin minn := maxlongint; readln(n); for i := 1 to n - 1 do begin readln(x, y); add1(x, y, 1); add1(y, x, 0); end; prework(1); init(1); repeat1(1); for i := 1 to n do begin if(sx[i] <= minn)then begin minn := sx[i]; end1 := i; end; end; writeln(minn); for i := 1 to n do if(sx[i] = minn) and (end1 <> i) then write(i,' '); writeln(end1); end.
題目描述 |
---|
立刻假期就要到了,THU的神犇Leopard假期裏都不忘學霸,如今有好多門功課,每門功課都耗費他1單位時間來學習。 他的假期從0時刻開始,有1000000000個單位時間(囧rz)。在任意時刻,他均可以任意一門功課(編號1~n)來學習。 由於他在每一個單位時間只能學習一門功課,而每門功課又都有一個截止日期,因此他很難完成全部n門功課。 對於第i門功課,有一個截止時間Di,若他能學完這門功課,他可以得到知識Pi。 在給定的功課和截止時間下,Leopard可以得到的知識最多爲多少呢?
輸入 |
---|
第一行,一個整數n,表示功課的數目 接下來n行,每行兩個整數,Di和Pi
輸出 |
---|
輸出一行一個整數,表示最多學得的知識數
樣例輸入 |
---|
3 2 10 1 5 1 7
樣例輸出 |
---|
17 【樣例說明】 第一個單位時間學習第3個功課(1,7),而後在第二個單位時間學習第1個功課(2,10)
本題的算法是貪心或DP,但我用的是堆(什麼鬼啊)。
一眼看下去,想都不用想,排個序,按時間來排。
我用的堆是小根堆,由於若是存不下(時間不夠),我是會拿當前最小的位置放新來的(必定要比最小的大啊!\(\Leftarrow\)廢話),固然堆這種東西是存一個,排(序)一個的(廢話×2)。
for (int i = 1; i <= n; i++) { if(heap.size() < a[i].x) //時間夠 { ans += a[i].y; heap.push(a[i].y); } else //時間不夠 { if(heap.top() < a[i].y) //並且比"最小的"大 { ans -= heap.top(); heap.pop(); heap.push(a[i].y); ans += a[i].y; } } }
Q:在?爲啥咕咕。
A:我就是不寫,啊啊啊啊,寫這些一大堆,啊啊啊
Q:爲啥又開始寫了???
A:由於我想寫。。。
Q:在?爲啥B組
A:由於我想去。。。