Gym - 100676G Training Camp (状压dp)
G. Training Camp
[ Color: Yellow ]
Montaser is planning to train very hard for ACM JCPC 2015; he has prepared a list with n topics
to study in the next n days, one topic every day.
Montaser knows that some topics depend on other topics, so he asked coach Fegla and got a list
of m constraints on the order in which he should study these topics.
Also, coach Fegla told him that when he studies topic x on the kth day (1 ≤ k ≤ n), his level will
increase by k*Wx, where Wx is a weight for topic x, representing how hard it is.
Given the list of topics, the weight of each topic, and the list of constrains, can you tell Montaser
what is the maximum level he can reach in these n days? He is currently at level 0 L.
Input
The first line of input contains one integer T representing the number of test cases (1 ≤ T ≤ 128).
The first line of each test case contains two integers: n and m (1 ≤ n ≤ 18).
The next n lines, each contains the title of one of the topics followed by a space, then an integer
W that represents the weight of this topic (1 ≤ W ≤ 100).
The next m lines are of the form: Topic 1 --> Topic 2, which means that Topic 1 must be studied
before Topic 2.
Titles contain only English letters and spaces (no more than 40 characters).
Test cases are separated by a blank line.
Output
For each test case, print the maximum level that Montaser can reach.
Sample Input
1
3 2
Implementation 3
Dynamic Programming 10
Greedy 7
Greedy --> Dynamic Programming
Implementation --> Dynamic
Programming
Sample Output
47
题意:
就是一个人要在n天学完n门课程,每天学习一门,在第i天学习第w[i]门课程他的姿势水平会增加i * w[i],然后这些课程有先后顺序,类似于拓扑排序的
顺序,比如:a -> b, c -> b, c -> a就表示学习a之前要先学习c,学习b之前要先学习a和c,求他能达到的最高的姿势水平。
思路:
输入比较烦人,考虑到n只有18,很容易想到状态压缩,用dp[i]表示状态为i的时候能达到的最高姿势水平,那么dp[i]的值就可以通过枚举状态i的为1的位来得到当前的值
比如dp[010011(2)] = max(dp[000011(2)] + 3(day) * w[4], dp[010001(2) + 3(day) * w[1], dp[010010(2)] + 3(day) * w[0])来得到。复杂度为
T*n*logn但是T比较大 满状态的话复杂度是128*18*2^18 = 6e8,很容易被卡常。所以做个优化,就是因为不是没个状态都是可以的,因为要按照拓扑排序的
顺序,所以我们在转移方程的时候把能够存在的状态给标记一下,这样就有很多状态不是o(n)而是o(1)了。
代码:
/** @xigua */
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
#include<queue>
#include<set>
#include<string>
#include<map>
#include<climits>
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 1e2 + 5;
const int mod = 1e9 + 7;
const int INF = 1e8 + 5;
const ll inf = 1e15 + 5;
const db eps = 1e-9;
int w[maxn], dp[1<<20];
map<string, int> mp;
int n, m, pre[25]; void solve() {
mp.clear();
cin >> n >> m; cin.get();
for (int k = 0; k < n; k++) {
string s, name; int xx = 0;
getline(cin, s); int flag = 1;
for (int i = 0; i < s.size(); i++) {
if (flag && s[i+1] >= '0' && s[i+1] <= '9') {
flag = 0; continue;
}
if (flag) name += s[i];
if (!flag) xx = xx * 10 + s[i] - '0';
}
mp[name] = k; w[k] = xx;
}
memset(pre, 0, sizeof(pre));
for (int i = 1; i <= m; i++) {
string s, xx, hh;
getline(cin, s); int flag = 0;
for (int j = 0; j < s.size(); j++) {
if (s[j+1] == '-') {
flag = 1; continue;
}
if (flag == 1 && s[j] == ' ') {
flag = 2; continue;
}
if (flag == 0) xx += s[j];
if (flag == 2) hh += s[j];
}
pre[mp[hh]] |= (1 << mp[xx]); //如果要学习第mp[hh]课程的话要先学习mp[xx]课程
}
for (int i = 1; i < (1 << n); i++)
dp[i] = -INF;
dp[0] = 0;
bool can[1<<19] = {0}; can[0] = 1;
for (int i = 0; i < (1 << n); i++) {
if (!can[i]) continue; //不存在当前状态就跳过
int num = 0;
for (int j = 0; j < n; j++) {
num += ((i >> j) & 1);
}
for (int j = 0; j < n; j++) {
int xx = i | (1<<j);
if (xx != i) {
if ((i & pre[j]) != pre[j]) continue; //状态i中是否包括了要学习课程j的所以课程
can[xx] = true;
dp[xx] = max(dp[xx], dp[i] + (num+1) * w[j]);
}
}
}
cout << dp[(1<<n) - 1] << endl;
} int main() {
//cin.sync_with_stdio(false);
//freopen("isharp.in", "r", stdin);
//freopen("isharp.out", "w", stdout);
int t = 1; cin >> t; while (t--) {
solve();
}
return 0;
}
/*
1
3 2
Implementation 3
Dynamic Programming 10
Greedy 7
Greedy --> Dynamic Programming
Implementation --> Dynamic Programming
*/
Gym - 100676G Training Camp (状压dp)的更多相关文章
- 状压dp Gym - 100676G
http://codeforces.com/gym/100676 题目大意: 给你n个科目,m个关系,例如A->B,表示要学习B科目,一定要把A科目学习掉.同理,如果还有C->B,那么,B ...
- Codeforces Gym 100015F Fighting for Triangles 状压DP
Fighting for Triangles 题目连接: http://codeforces.com/gym/100015/attachments Description Andy and Ralph ...
- Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP
Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...
- 2014 Super Training #1 B Fix 状压DP
原题: HDU 3362 http://acm.hdu.edu.cn/showproblem.php?pid=3362 开始准备贪心搞,结果发现太难了,一直都没做出来.后来才知道要用状压DP. 题意: ...
- CCPC-Wannafly Winter Camp Day3 Div1 - 精简改良 - [生成树][状压DP]
题目链接:https://zhixincode.com/contest/14/problem/D?problem_id=206 样例输入 1 5 5 1 2 1 1 3 1 2 4 1 2 5 1 ...
- 【CCPC-Wannafly Winter Camp Day3 (Div1) D】精简改良(状压DP)
点此看题面 大致题意: 给你一张图,定义\(dis(i,j)\)为\(i\)与\(j\)的最短距离,现要求删去若干条边,使得图仍然联通,且\(\sum_{i=1}^n\sum_{j=i+1}^ndis ...
- codeforces Diagrams & Tableaux1 (状压DP)
http://codeforces.com/gym/100405 D题 题在pdf里 codeforces.com/gym/100405/attachments/download/2331/20132 ...
- HDUOJ Clear All of Them I 状压DP
Clear All of Them I Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 122768/62768 K (Java/Oth ...
- 暑假集训 || 状压DP
emm 位操作实现技巧: 获得第i位的数据: if(!(data & (1<< i))) 则data的第 i 位为0,else 为 1 设置第i位为1,data=(data | ...
随机推荐
- 「USACO」「LuoguP2731」 骑马修栅栏 Riding the Fences(欧拉路径
Description Farmer John每年有很多栅栏要修理.他总是骑着马穿过每一个栅栏并修复它破损的地方. John是一个与其他农民一样懒的人.他讨厌骑马,因此从来不两次经过一个栅栏.你必须编 ...
- 《算法概论》第八章的一些课后题目 关于NP-Complete Problem
8.3 STINGY SAT STINGY SAT is the following problem: given a set of clauses (each a disjunction of li ...
- bzoj1038&&500AC!
序列dp 先开始想了一个类似区间dp的东西...少了一维 然后发现似乎不太对,因为女生的最大差和男生的最大差并不相等 dp[i][j][x][y]表示当前有i个人,j个男生,男生和女生的后缀最大差是x ...
- pymssql读取varchar字段中文显示乱码的问题分析
问题 用python的pymssql模块读取旧业务系统后台SQL Server 2000数据库展示数据为乱码 开发环境 操作系统:windows 8 数据库 MS SQL Server 2000,默认 ...
- View Controller Programming Guide for iOS---(七)---Resizing the View Controller’s Views
Resizing the View Controller’s Views A view controller owns its own view and manages the view’s cont ...
- UVaLive 7455 Linear Ecosystem (Gaussi 消元)
题意:对一个k元向量, 每次左乘一个k*k的矩阵得到新的向量.问经过一定次数的左乘后,能否使得该向量不再变化. (同时要求此时向量非零). 析:设初始向量为A,矩阵为P.由于每次矩阵P都是左乘A, 那 ...
- 基于 Algebird 谈一谈代数数据类型在数据聚合中的应用
此文已由作者肖乃同授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 代数数据类型是指满足一定数学特性的数据类型, 这些特性使得计算能够很方便的并行化,在Scalding和 S ...
- python __builtins__ enumerate类 (21)
21.'enumerate', 用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中. class enumerate(object ...
- oracle常用的一些查询命令
.查看所有用户 select * from dba_users; select * from all_users; select * from user_users; .查看用户或角色系统权限(直接赋 ...
- python三行代码实现快速排序
def quick_sort(array): if len(array) < 2: return array return quick_sort([lt for lt in array[1:] ...