loj6395. 「THUPC2018」城市地铁规划 / City

本文介绍了一种使用动态规划构建一棵具有最大权值和的树的方法,通过prufer序列特性,实现完全背包问题求解,同时记录转移路径以输出构建方案。

题意

给定一个函数\(c(x)\)表示度数为\(x\)的节点权值。求构建一棵树,使得权值和最大。
\(n \leq 3000\)

题解

考虑要构建一棵树,prufer序列会是一个不错的选择。
根据prufer的性质,每个点出现的次数为度数减1,并且总序列长度为\(n - 2\)
这样就可以做一个完全背包,体积为\(x - 1\),价值为\(c(x)\),(其中\((1 \leq x \leq n - 1)\))的物品每种有无限个。
最后求出背包大小为\(n - 2\)的最大价值和。
但是注意到体积为0也有价值,却不能放进背包更新。
有一个方法:开始时把\(n\)个体积为\(0\)的物品放进背包,然后剩下的过程就是每次将若干个体积为\(0\)的物品替换为体积为\(x\)的物品。
\(f_0 = n * c_1\),更新的时候比较\(f_j\)\(f_{j - (i - 1)} + c_i - c_1\),最后答案为\(f_{n - 2}\)
但是本题还要输出方案。这就要求dp的时候记录转移的前驱。利用这个我们可以计算出最终的树上的\(n\)个点在prufer序列上出现次数。
然后利用这个贪心的思想构建这棵树(度数越小的放末尾,事实证明,把所有叶子结点放在末尾即可),注意根的特殊性(对于非根节点,在prufer序列出现次数 = 儿子数;对于根,在prufer序列出现次数 = 儿子数 - 1)。
复杂度\(\mathcal O(n ^ 2)\)

#include <bits/stdc++.h>
using namespace std;
const int N = 3005, mod = 59393;
int n, k, tot, a[N], c[N], f[N], g[N], d[N];
void dfs (int x) {
    for (int i = 1; i <= d[x]; ++i) {
        printf("%d %d\n", x, ++tot);
        dfs(tot);
    }
}
int main () {
    scanf("%d%d", &n, &k);
    for (int i = 0; i <= k; ++i) {
        scanf("%d", &a[i]);
    }
    for (int i = 0; i <= n; ++i) {
        for (int j = k; ~j; --j) {
            c[i] = c[i] * i % mod + a[j];
            c[i] %= mod;
        }
    }
    if (n == 1) {
        printf("0 %d\n", c[0]);
        return 0;
    }
    if (n == 2) {
        printf("1 %d\n",2 * c[1]);
        printf("1 2\n");
        return 0;
    }
    f[0] = n * c[1];
    for (int i = 2; i <= n; ++i) {
        for (int j = i - 1; j <= n - 2; ++j) {
            if (f[j] < f[j - (i - 1)] + c[i] - c[1]) {
                f[j] = f[j - (i - 1)] + c[i] - c[1];
                g[j] = j - (i - 1);
            }
        }
    }
    printf("%d %d\n", n - 1, f[n - 2]);
    for (k = n - 2; k; k = g[k]) {
        d[++d[0]] = k - g[k];
    }
    sort(d + 1, d + d[0] + 1);
    ++d[1];
    dfs(tot = 1);
    return 0;
}

转载于:https://www.cnblogs.com/psimonw/p/11509064.html

# P3456 [POI 2007] GRZ-Ridges and Valleys ## 题目描述 **译自 POI 2007 Stage 2. Day 0「[Ridges and Valleys](https://szkopul.edu.pl/problemset/problem/rd6H05Dm8ME79sO3U9_f_ga_/site/?key=statement)」** 给定一个 $n \times n$ 的网格状地图,每个方格 $(i,j)$ 有一个高度 $w_{ij}$。如果两个方格有公共顶点,则它们是相邻的。 定义山峰和山谷如下: * 均由地图上的一个连通块组成; * 所有方格高度都相同; * 周围的方格(即不属于山峰或山谷但山峰或山谷相邻的格子)高度均大于山谷的高度,或小于山峰的高度。 求地图内山峰和山谷的数量。特别地,如果整个地图方格的高度均相同,则整个地图既是一个山谷,也是一个山峰。 ## 输入格式 第一行一个整数 $n$ ($2 \le n \le 1000$),表示地图的大小。 接下来 $n$ 行每行 $n$ 个整数表示地图。第 $i$ 行有 $n$ 个整数 $w_{i1}, w_{i2}, \ldots, w_{in} (0 \le w_{ij} \le 1\ 000\ 000\ 000)$,表示地图第 $i$ 行格子的高度。 ## 输出格式 输出一行两个整数,分别表示山峰和山谷的数量。 ### 样例解释 ![](https://cdn.luogu.com.cn/upload/image_hosting/yubj6du3.png) ![](https://cdn.luogu.com.cn/upload/image_hosting/7ct18655.png) 翻译来自于 [LibreOJ](https://loj.ac/p/2653)。 ## 输入输出样例 #1 ### 输入 #1 ``` 5 8 8 8 7 7 7 7 8 8 7 7 7 7 7 7 7 8 8 7 8 7 8 8 8 8 ``` ### 输出 #1 ``` 2 1 ``` ## 输入输出样例 #2 ### 输入 #2 ``` 5 5 7 8 3 1 5 5 7 6 6 6 6 6 2 8 5 7 2 5 8 7 1 0 1 7 ``` ### 输出 #2 ``` 3 3 ```# P3456 [POI 2007] GRZ-Ridges and Valleys ## 题目描述 **译自 POI 2007 Stage 2. Day 0「[Ridges and Valleys](https://szkopul.edu.pl/problemset/problem/rd6H05Dm8ME79sO3U9_f_ga_/site/?key=statement)」** 给定一个 $n \times n$ 的网格状地图,每个方格 $(i,j)$ 有一个高度 $w_{ij}$。如果两个方格有公共顶点,则它们是相邻的。 定义山峰和山谷如下: * 均由地图上的一个连通块组成; * 所有方格高度都相同; * 周围的方格(即不属于山峰或山谷但山峰或山谷相邻的格子)高度均大于山谷的高度,或小于山峰的高度。 求地图内山峰和山谷的数量。特别地,如果整个地图方格的高度均相同,则整个地图既是一个山谷,也是一个山峰。 ## 输入格式 第一行一个整数 $n$ ($2 \le n \le 1000$),表示地图的大小。 接下来 $n$ 行每行 $n$ 个整数表示地图。第 $i$ 行有 $n$ 个整数 $w_{i1}, w_{i2}, \ldots, w_{in} (0 \le w_{ij} \le 1\ 000\ 000\ 000)$,表示地图第 $i$ 行格子的高度。 ## 输出格式 输出一行两个整数,分别表示山峰和山谷的数量。 ### 样例解释 ![](https://cdn.luogu.com.cn/upload/image_hosting/yubj6du3.png) ![](https://cdn.luogu.com.cn/upload/image_hosting/7ct18655.png) 翻译来自于 [LibreOJ](https://loj.ac/p/2653)。 ## 输入输出样例 #1 ### 输入 #1 ``` 5 8 8 8 7 7 7 7 8 8 7 7 7 7 7 7 7 8 8 7 8 7 8 8 8 8 ``` ### 输出 #1 ``` 2 1 ``` ## 输入输出样例 #2 ### 输入 #2 ``` 5 5 7 8 3 1 5 5 7 6 6 6 6 6 2 8 5 7 2 5 8 7 1 0 1 7 ``` ### 输出 #2 ``` 3 3 ```# P3456 [POI 2007] GRZ-Ridges and Valleys ## 题目描述 **译自 POI 2007 Stage 2. Day 0「[Ridges and Valleys](https://szkopul.edu.pl/problemset/problem/rd6H05Dm8ME79sO3U9_f_ga_/site/?key=statement)」** 给定一个 $n \times n$ 的网格状地图,每个方格 $(i,j)$ 有一个高度 $w_{ij}$。如果两个方格有公共顶点,则它们是相邻的。 定义山峰和山谷如下: * 均由地图上的一个连通块组成; * 所有方格高度都相同; * 周围的方格(即不属于山峰或山谷但山峰或山谷相邻的格子)高度均大于山谷的高度,或小于山峰的高度。 求地图内山峰和山谷的数量。特别地,如果整个地图方格的高度均相同,则整个地图既是一个山谷,也是一个山峰。 ## 输入格式 第一行一个整数 $n$ ($2 \le n \le 1000$),表示地图的大小。 接下来 $n$ 行每行 $n$ 个整数表示地图。第 $i$ 行有 $n$ 个整数 $w_{i1}, w_{i2}, \ldots, w_{in} (0 \le w_{ij} \le 1\ 000\ 000\ 000)$,表示地图第 $i$ 行格子的高度。 ## 输出格式 输出一行两个整数,分别表示山峰和山谷的数量。 ### 样例解释 ![](https://cdn.luogu.com.cn/upload/image_hosting/yubj6du3.png) ![](https://cdn.luogu.com.cn/upload/image_hosting/7ct18655.png) 翻译来自于 [LibreOJ](https://loj.ac/p/2653)。 ## 输入输出样例 #1 ### 输入 #1 ``` 5 8 8 8 7 7 7 7 8 8 7 7 7 7 7 7 7 8 8 7 8 7 8 8 8 8 ``` ### 输出 #1 ``` 2 1 ``` ## 输入输出样例 #2 ### 输入 #2 ``` 5 5 7 8 3 1 5 5 7 6 6 6 6 6 2 8 5 7 2 5 8 7 1 0 1 7 ``` ### 输出 #2 ``` 3 3 ```
08-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值