「NOIp2018」题解
emmm,今天开始从2018向前做NOIp的真题,并写一些题解,太蒻了Orz
emmm,今天开始从2018向前做NOIp的真题,并写一些题解,太蒻了Orz
n, m, q
点数、边数、问题数x, y
需要合并的两个数ufs[]
并查集find(int)
查找并查集中一个数的祖先unionn(int, int)
合并两个数所在集合
1 | const int maxn = 10010; |
1 | template <typename T> |
1 | template <typename T> |
vector<数据类型> 名;
例 vector<int> a;
a.size();
读取大小a.resize();
改变大小a.push_back(x);
尾部添加元素xa.pop_back();
删除最后一个元素a.clear();
清空a.empty()
询问是否为空(bool类型)a[]
访问元素(可修改)
头文件: #include <queue>
参数: priority_queue<Type, Container, Functional>
Type
数据类型 不可省
Container
容器(vector,deque)默认vector
Functional
比较方式,默认operator <
大根堆
与queue类似
priority_queue<int, vector<int>, greater<int> > q;
使用仿函数greater<>
1 | struct Node |
1 | bool operator < (Node a, Node b) |
x值大的优先级低,排在队前
x相等,y大的优先级低
1 | struct cmp |
有 $n$ 件物品,和一容积为 $V$ 的背包,第 $i$ 件物品的体积为 $w_i$ ,价值为 $c_i$ 。将第几件物品装入,使体积不超过总体积,且价值和最大,求最大价值。
由题意易知状态转移方程: $F_{i,j} = max(F_{i-1,j}\ , F_{i-1,j-w_i} + c_i)$
$F_{i, j}$ 为前 $i$ 件物品放入容量为 $V$ 的背包中最大价值
时间复杂度 $O(n\times V)$ ,空间复杂度 $O(n\times V)$
注意倒序,保证f[n][V]
为结果
1 | for (int i = 1; i <= n; ++i) |
降至一维数组
时间复杂度 $O(n\times V)$ ,空间复杂度 $O(V)$
1 | for (int i = 1; i <= n; ++i) |
有 $n$ 种物品(每种 无限件 ),和一容积为 $V$ 的背包,第 $i$ 种物品的体积为 $w_i$ ,价值为 $c_i$ 。将第几种物品取任意件装入,使体积不超过总体积,且价值和最大,求最大价值。
将01背包第二个循环改为正序即可
状态转移方程:$F_j = max(F_j\ , F_{j-w_i}+c_i)$
1 | for (int i = 1; i <= n; ++i) |
有 $N$ 种物品,和一容积为 $V$ 的背包,第 $i$ 种物品有 $n_i$ 件,体积为 $w_i$ ,价值为 $c_i$ 。将第几件物品装入,使体积不超过总体积,且价值和最大,求最大价值。
状态转移方程:$F_{i,v} = max(F_{i-1,v-k\times w_i} + k\times c_i | 0\leqslant k\leqslant n_i)$
时间复杂度:$O(V\times \sum{n_i})$
1 | for (int i = 1; i <= N; ++i) |
把 $n_i$ 件一种物品化为单独的 $n_i$ 件物品即可
时间复杂度:$O(V\times \sum{n_i})$
框架略
$$
n_i\to 1+2+4+\dots +2^{k-1}+\dots +(n_i-2^k+1)
$$
$$
\sum{n_i}\to \sum{\log_2{n_i}}
$$
时间复杂度:$O(V\times \sum{\log_2{n_i}})$
1 | for (int i = 1; i <= n; ++i) |
有 $N$ 种物品,和一容积为 $V$ 的背包,第 $i$ 种物品有 $n_i$ 件或无穷件,体积为 $w_i$ ,价值为 $c_i$ 。将第几件物品装入,使体积不超过总体积,且价值和最大,求最大价值。
1 | for (int i = 1; i <= N; ++i) |
有 $N$ 件物品,容积为 $V,U$ 的两个背包,每件物品有两种费用,选择物品需要付出两种代价,第 $i$ 件代价为 $a_i,b_i$,价值为 $c_i$。将第几件物品装入,使体积不超过总体积,且价值和最大,求最大价值。
改为二维数组即可
状态转移方程:$F_{v,u} = max(F_{v,u}\ , F_{v-a_i,u-b_i} + c_i)$
$F_{v,u}$ 表示前面的物品付出代价分别为 $v,u$ 时的最大价值
框架略
循环顺序
v = V..0 u = U..0
v = 0..V u = 0..U
有 $K$ 组物品, $V$ 的背包,第 $k$ 组有 $N_k$ 件物品,第 $i$ 件物品的体积为 $w_i$ ,价值为 $c_i$ ,每组中只能选一件物品。将第几件物品装入,使体积不超过总体积,且价值和最大,求最大价值。
1 | for (int k = 1; k <= K; ++k) |
状态转移方程:$F_{i,v} = sum(F_{i-1,v}, F_{i-1,v-w_i})\ \ \ (F_{0,0} = 1)$
1 | f[0] = 1; |
heap[]
堆heap_size
堆大小put(int)
压入一个数get()
弹出堆顶
1 | int heap[maxn]; |
1 | int heap[maxn]; |
n, m, s
点数、边数、源点cnt, head[], edge[], add(int, int, int)
链式前向星dist[]
各点到源点路径长vis[]
记录
1 | const int maxn = 10010; |
n, m, _map[][]
点数、边数、邻接矩阵dist[]
树根到各点路径长pre[]
生成树路径
1 | const int maxn = 101; |