Codeforces Round #90 C题(三维递推DP)
来源:互联网 发布:民间子平何知章388句 编辑:程序博客网 时间:2024/05/17 08:41
http://www.codeforces.com/contest/119/problem/C
题意:一个学年有N天,每天必须从M个科目中挑选出一个。每个科目有3个属性,ai、bi、ci,表示第i个科目的作业量在[ai, bi]中,该科目的难度系数为ci。安排科目时,必须一天比一天的难度系数大除第一天外,每一天的科目还要安排作业量,除第一天外,每一天的作业量必须符合now = past+k or now = past*k。问能否按要求安排完N天的作业,如果能则输出总作业量最大的安排方案,输出格式见Sample。
这题用递推思路比较清晰,dp[i][j][k]表示第j个科目作业量为k的状态,安排在第i天后的总作业量,但作业量的确定值太大,而作业量的范围<=100,所以第三维只需要保存作业量最小值的增量即可。
做法是将科目先按ci排个序、记录原来的位置,再初始化第一天的安排情况,然后一个循环不断加深天数,循环里依次更新能够转移的状态(暴力枚举),并顺便记录下前驱状态方便回溯路径。最后的工作就是找出第n天是否存在作业量为正的状态,不存在则没有合法方案,存在则选出最大值,回溯路径、打印。
一开始,我的想法是只开二维,没有多开一维空间来记录当前安排到的天数,结果一直在“保证能安排的天数尽可能多”和“保证当前安排的总作业量最大”之间纠结(缺乏DP的触觉),后来看了队友Band的代码,才恍然大悟,只要多开一维来记录安排天数的深度,则DP时只需关注总作业量最大就可以了……另外代码中混用了int 和 __int64,不放心的话可以全部改成__int64 or long long ~~
// 90 MS#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<stack>using namespace std; struct Data { __int64 a, b, c; int len, pos; // len是作业量的最大增量,pos记录当前科目的原始位置}o[100];__int64 dp[110][110][110];pair<int, __int64> pre[110][110][110];// 分别记录前驱状态的科目、作业量增量 int f[110];int n, m, k; bool cmp(Data a, Data b) { return a.c < b.c; } int main() { while(cin>>n>>m>>k) { memset(dp, 0, sizeof(dp)); for(int i = 1; i <= m; ++i) { cin>>o[i].a>>o[i].b>>o[i].c; o[i].len = o[i].b - o[i].a; o[i].pos = i; } sort(o+1, o+m+1, cmp); for(int i = 1; i <= m; ++i) { for(int j = 1; j <= m; ++j) if(o[j].pos == i) { f[j] = i; break; } } //------------------------------初始化 for(int i = 1; i <= m; ++i) { for(int j = 0; j <= o[i].len; ++j) { dp[1][i][j] = o[i].a + j; } } // 核心DP递推部分 for(int dep = 1; dep < n; ++dep) { // 当前已经安排了科目的天数 for(int i = dep+1; i <= m; ++i) { // 枚举有可能更新状态的科目 for(int j = 1; j < i; ++j) { // 枚举难度系数更小的科目,尝试更新第i个科目的状态 if(o[i].c == o[j].c) continue; for(int jj = 0; jj <= o[j].len; ++jj) { // 枚举第j个科目的作业量为aj + jj时的状态 if(dp[dep][j][jj] == 0) continue; __int64 t = o[j].a + jj; if(o[i].a <= t+k && t+k <= o[i].b) { __int64 u = t+k - o[i].a; if(dp[dep][j][jj] + o[i].a + u > dp[dep+1][i][u]) { dp[dep+1][i][u] = dp[dep][j][jj] + o[i].a + u; pre[dep+1][i][u].first = j; pre[dep+1][i][u].second = jj; } } // 两种转移的情况、记录路径 if(o[i].a <= t*k && t*k <= o[i].b) { __int64 u = t*k - o[i].a; if(dp[dep][j][jj] + o[i].a + u > dp[dep+1][i][u]) { dp[dep+1][i][u] = dp[dep][j][jj] + o[i].a + u; pre[dep+1][i][u].first = j; pre[dep+1][i][u].second = jj; } } } } } } //-------------------------------------找出作业量最大的状态 int x, y; __int64 Max = 0; for(int i = 1; i <= m; ++i) { for(int j = 0; j <= o[i].len; ++j) { //cout<<dp[n][i][j]<<" "; if(dp[n][i][j] > Max) { Max = dp[n][i][j]; x = i; y = j; } } //cout<<endl; } //------------------------------判断是否有合适方案,回溯输出 if(!Max) { cout<<"NO"<<endl; continue; } cout<<"YES"<<endl; stack< pair<int, __int64> > sta; for(int i = n; i >= 1; --i) { int t1 = x, t2 = y; x = pre[i][t1][t2].first; y = pre[i][t1][t2].second; if(i == 1) sta.push(make_pair(t1, dp[i][t1][t2])); else sta.push(make_pair(t1, dp[i][t1][t2] - dp[i-1][x][y])); } while(!sta.empty()) { cout<<f[sta.top().first]<<" "<<sta.top().second<<endl; sta.pop(); } } return 0;}
- Codeforces Round #90 C题(三维递推DP)
- CodeForces Round#229 DIV2 C 递推DP
- codeforces Round #369 (Div. 2) C. Coloring Trees (三维DP)
- Codeforces Round #369 (Div. 2) C. Coloring Trees 三维dp
- Codeforces Round #240 (Div. 2)(D:dp递推)
- Codeforces Round #245 (Div. 1)B 递推DP
- Codeforces Round #369 (Div. 2) -- C. Coloring Trees (三维DP)
- Codeforces Round #269 (Div. 2) C 递推+打表
- Codeforces Round #335 (Div. 2) (C 思维题(递推,贪心))
- codeforces 212 C DP 递推 计数 破环
- CodeForces 132C Logo Turtle 四维DP 递推
- Codeforces Beta Round #90, problem: (C) Education Reform DP
- 【dp】Codeforces Round #110 (Div. 1) C
- codeforces round# 302 (div1 C) (状压dp)
- 【DP】Codeforces Round #336 (Div. 2) C
- Codeforces Round #363 (Div. 2) C dp
- Codeforces Round #303 (Div. 2) C dp
- Codeforces Round #286 (Div. 2) C dp
- java post 访问URL
- Base64算法的前世今生(三)
- Solr 中文分词器
- linux特点--------------韩顺平
- 2012年ArcGIS技术博客年终总结
- Codeforces Round #90 C题(三维递推DP)
- Android ScrollView与ListView,GridView共存冲突解决方案
- XMLHTTPRequest对象
- 清理 oracle lobsegment
- POJ 1946(三维DP)
- 二叉树的后序遍历的非递归算法(二)
- 聊了个斋【转载】
- Android开发ScrollView 事件冲突问题 .
- html jquery显示和隐藏的小例子