Codeforces Round #436 (Div. 2)E,F详解
来源:互联网 发布:多益网络客服电话 编辑:程序博客网 时间:2024/06/05 02:28
鉴于太多人把D做出来了,实际上D就是道模拟简单题,所以本篇博客并没有D的题解。如果有需要的读者可以联系博主,博主会很热心的为你解释的(笑)。。
E题题解:Polycarp家着火了。。他家里有n个值钱的东西,每一个东西有一个营救需要的时间和一个烧毁需要的时间。问Polycarp能救出的东西的最大价值为多少,并输出营救顺序。
思路:裸的01背包问题。。如果不明白01背包问题可以看看紫书的动规专题。
思路出来了,博主觉得有必要讲的两点就是,一,它和01背包问题唯一不同的是有一个限制时间,不像01背包啥时候都可以拿,它拿某个物品的时间是一段区间。二,能拿某个物品的时间怎么算,首先状态转移方程式为
dp[T]=max(dp[T],dp[T-t[i]]+w[i]),显然T< d[i],并且T>t[i].所以只会更新该区间的值,但更新完了肯定会影响后面的T(从这个式子就可以看出),所以为了复杂度低(你也可以更新后面的T,加个判断即可),首先把物品按照d排个序,先取小的,再取大的,这样就可保证再更新大的时候小的已经全部被更新了。
代码如下:
#include<iostream>#include<vector>#include<algorithm>using namespace std;struct node{ int t, d, p; int idx; bool operator<(const node &b)const { return d < b.d; }}nodes[205];vector<int>V[2005];int dp[2005];int main(){ int n; cin >> n; for (int i = 1;i <= n;i++) { scanf("%d%d%d", &nodes[i].t, &nodes[i].d, &nodes[i].p); nodes[i].idx = i; } sort(nodes + 1, nodes + 1 + n); for(int i=1;i<=n;i++) for (int j = nodes[i].d - 1;j >= nodes[i].t;j--) { if (dp[j] < dp[j - nodes[i].t] + nodes[i].p) { dp[j] = dp[j - nodes[i].t] + nodes[i].p; V[j] = V[j - nodes[i].t]; V[j].push_back(nodes[i].idx); } } int theans = 0; int idx=-1; for(int i=0;i<=2000;i++) if (theans < dp[i]) { theans = dp[i]; idx = i; } cout << theans << endl; if (idx == -1) { cout << 0 << endl; return 0; } int Size = V[idx].size(); cout << Size << endl; for (int i = 0;i < Size;i++) { if (i != 0)printf(" "); printf("%d", V[idx][i]); } return 0;}
F题题意:给你一个图,有q次询问,从s到t的结点最小字典序路径中的第k个结点是谁。
思路:这题好啊,让博主学习到了图上的倍增。另外也让博主领悟到了一个小套路,即如果题目给你一个k,让你求路径上的第k个点,这大概就需要用倍增的思想了。
思路挺简单的,那么如何用倍增呢?请读者仔细看代码,并理解从中倍增的奥妙和如何用倍增判断是环的。
#include<iostream>#include<vector>#include<algorithm>#include<cstring>using namespace std;const int maxn = 3005;const int maxq = 4e5 + 10;vector<int>G[maxn], TO[maxn];vector < pair<pair<int, int>, int>>Q[maxq];bool vis[maxn];#define MP(x,y) make_pair(x,y)void dfs(int node){ if (vis[node])return; vis[node] = 1; for (int i : TO[node]) dfs(i);}int st[maxn][13];int ans[maxq];int main(){ int n, m, q; cin >> n >> m >> q; int u, v; for (int i = 1;i <= m;i++) { scanf("%d%d", &u, &v); G[u].push_back(v); TO[v].push_back(u); } int s, t, k; for (int i = 1;i <= q;i++) { scanf("%d%d%d", &s, &t, &k); Q[t].push_back(MP(MP(s, k), i)); } for (int i = 1;i <= n;i++)sort(G[i].begin(), G[i].end()); for (int i = 1;i <= n;i++)if(Q[i].size()) { memset(vis, 0, sizeof(vis)); dfs(i); memset(st, 0, sizeof(st)); for (int j = 0;j < 13;j++)st[n + 1][j] = n + 1; for (int j = 1;j <= n;j++) { if (j == i)st[j][0] = n + 1; else if (vis[j]) { for (int v : G[j]) { if (!vis[v])continue; st[j][0] = v; break; } } } for (int j = 1;j < 13;j++) for (int u = 1;u <= n;u++)if(vis[u]) st[u][j] = st[st[u][j - 1]][j - 1]; for (auto it : Q[i]) { int s = it.first.first; int k = it.first.second - 1; int id = it.second; if (vis[s]) { if (st[s][12] == n + 1) { for (int j = 0;j < 13;j++) if (k&(1 << j)) s = st[s][j]; if (s != n + 1) ans[id] = s; else ans[id] = -1; } else ans[id] = -1; } else { ans[id] = -1; } } } for (int i = 1;i <= q;i++) cout << ans[i] << endl; return 0;}
代码浑然天成啊。。。博主想解释为啥用离线,但感觉没必要,因为都这样写了,还能用在线不成。希望读者仔细阅读代码,学会了又有新姿势上分了~
- Codeforces Round #436 (Div. 2)E,F详解
- Codeforces Round #441 Div. 2 E,F
- Codeforces Round #435 (Div. 2)C,D,E,F题目详解
- Codeforces Round #439 (Div. 2)E详解
- Codeforces Round #377 (Div. 2)(D.E.F)
- Codeforces Round #436 (Div. 2) E. Fire
- Codeforces Round #436 (Div. 2)E.Fire
- Codeforces Round #436 (Div. 2) E
- Codeforces Round #436 (Div. 2)E. Fire
- Codeforces Round #436 (Div. 2) E. Fire
- Codeforces Round 864F (Codeforces Round #436 Div. 2) F. Cities Excursions tarjan判环
- Codeforces Round #432 (Div. 2)C,D,E题目详解
- Codeforces Round #433(Div.2) C,D,E题目详解
- Codeforces Round #430(Div.2) C,D,E题目详解
- Codeforces Round #423 Div.2 A B C D E F
- Codeforces Round #424 Div.2 A B C D E F
- 解题报告:Codeforces Round #424 (Div. 2) A B C D E F
- Codeforces Round #436 (Div. 2) F. Cities Excursions
- [cnblogs镜像]Unity 动画资源与模型资源的区别
- 最大最小公倍数
- java学习初探十七之IO流
- suse12 开启ssh 远程连接
- 如何解决It's likely you're attempting to run Eclipse using the JRE instead of the JDK
- Codeforces Round #436 (Div. 2)E,F详解
- 求1+2+3+...+n
- python实现Android strings.xml文件自动在线翻译
- 孩子们的游戏(圆圈中最后剩下的数)
- 网络五层模型
- Android TV 官方教程简读1-Building Apps for TV
- Linux打包免安装的Qt程序
- 扑克牌顺子
- sharding-jdbc分库分表规则(2)-多表查询