$ \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:由于我想去。。。