传送门

题目大意:

有n(\(\le 15\))个作业,每个作业有个name, deadline(截止日期),cost(做作业花的时间),如果没有按时完成某个作业,惩罚分数为超出的时间,求一个合理的顺序使得惩罚分数最小,如果有多个方案分数相同,输出字典序最小的。

题目分析

看到\(n \le 15\)可知状压dp:dp[S]表示完成S状态的最小惩罚分数,转移也较为简单:$$dp[i | (1 << (j - 1))] = min(dp[S | (1 << (j - 1))], dp[i] + getTime(i) + cost[j] - deadline[j])$$。因为要输出方案,于是记录一个from数组表示这个状态是从哪个状态转移来的。又因为要求字典序最小,现将name排序,这样在转移时如果\(dp[i | (1 << (j - 1))] == dp[i] + getTime(i) + cost[j] - deadline[j])\),并且\(i | (1 << (j - 1)) < from[i]\),那么\(from[i] = i | (1 << (j - 1))\),来保证字典序最小。

code

#include<bits/stdc++.h>
using namespace std; const int N = 20, S = 33000, OO = 0x3f3f3f3f;
int n, dp[S], T, from[S];
vector<int> ans;
struct node{
string name;
int dl, cost;
inline bool operator < (const node &b) const {
return name < b.name;
}
}task[N]; inline int getTime(int s){
int ans = 0;
for (int i=0; (1<<i)<=s; i++)
if ((1<<i)&s)
ans += task[i + 1].cost;
return ans;
} inline void init(){
memset(dp, OO, sizeof dp), dp[0] = 0;
memset(from, 0, sizeof from);
ans.clear();
} inline int find(int x){
int l = 1, r = 15;
while (l<=r) {
int mid = (l + r) >> 1;
if (1<<(mid-1) == x) return mid;
else if (1<<(mid-1) > x) r = mid - 1;
else l = mid + 1;
}
return 0;
} int main(){
ios::sync_with_stdio(false);
cin.tie(NULL), cout.tie(NULL);
cin >> T;
while(T--){
init();
cin >> n;
for (int i=1; i<=n; i++) cin >> task[i].name >> task[i].dl >> task[i].cost;
sort(task + 1, task + n + 1);
for (int i=0; i<(1<<n); i++) {
for(int j=1; j<=n; j++) {
if (i&(1<<(j-1))) continue;
if (dp[i|(1<<(j-1))] > dp[i] + max(0, getTime(i) + task[j].cost - task[j].dl)) {
from[i|(1<<(j-1))] = i;
dp[i|(1<<(j-1))] = dp[i] + max(0, getTime(i) + task[j].cost - task[j].dl);
}
else if(dp[i|(1<<(j-1))] == dp[i] + max(0, getTime(i) + task[j].cost - task[j].dl)) {
if(i < from[i|(1<<(j-1))]) from[i|(1<<(j-1))] = i;
}
}
}
cout << dp[(1<<n)-1] << endl;
int now = (1<<n)-1;
while(now) {
int diff = now ^ (from[now]);
int pos = find(diff);
// cout << now << " " << from[now] << " " << diff << " " << pos << endl;
ans.push_back(pos);
now = from[now];
}
for(int i=ans.size()-1; i>=0; i--) cout << task[ans[i]].name << endl;
}
return 0;
}

HDU1074 Doing Home Work - 状压dp的更多相关文章

  1. kuangbin专题十二 HDU1074 Doing Homework (状压dp)

    Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  2. HDU1074 Doing Homework(状压dp)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1074 题意:给定有n门课的作业,每门课交作业有截止时间,和完成作业所花费的时间,如果超过规定时间完成,每超 ...

  3. HDU1074:Doing Homework(状压DP)

    Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  4. dp,状压dp等 一些总结

    也就作业几题而已,分析一下提醒 最重要的就是,记住,没用的状态无论怎么转移最后都会是没用的状态,所以每次转移以后的有值的状态都是有用的状态. 几种思考方向: 第一种:枚举当前的状态,转移成另外一个状态 ...

  5. 对状压dp的见解

    看了好几篇博客,终于对一些简单的状压dp有了点了解.就像HDU1074. 有个博客:https://blog.csdn.net/bentutut/article/details/70147989 感觉 ...

  6. 算法复习——状压dp

    状压dp的核心在于,当我们不能通过表现单一的对象的状态来达到dp的最优子结构和无后效性原则时,我们可能保存多个元素的有关信息··这时候利用2进制的01来表示每个元素相关状态并将其压缩成2进制数就可以达 ...

  7. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  8. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  9. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

随机推荐

  1. Weblogic问题汇总

    1. weblogic unable to get file lock问题 在项目使用过程中,非正常结束Weblogic进程导致Weblogic无法启动,出现以下错误: <BEA-141281& ...

  2. invalid syntax 无效语法

    python用的是spyder编译器, 再出现上一行少了个括号的时候. 在下一行显示有错误.

  3. angular设置全局变量,可修改监听变量

    创建service.module.ts import { NgModule, ModuleWithProviders } from '@angular/core'; import { SomeShar ...

  4. JS学习笔记 - fgm练习 - 限制输入框的字符类型 正则 和 || 或运算符的运用 i++和++i

    <script> window.onload = function(){ var aInp = document.getElementsByTagName('input'); var oS ...

  5. Valgrind的用法

    Valgrind是执行在Linux上一套基于仿真技术的程序调试和分析工具,它包括一个内核──一个软件合成的CPU,和一系列的小工具,每一个工具都能够完毕一项任务──调试.分析,或測试等. Valgri ...

  6. OC中对于属性的总结(@property)

    在没有属性之前: 对成员变量进行改动都要用到设置器:setter来改动 Person *per =[[Person alloc] init]; 对象通过设置器对成员变量内容进行修该 [per setN ...

  7. WebClient HttpWebRequest从网页中获取请求数据

    WebClient HttpWebRequest //HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(urlAddress) ...

  8. POJ 3041 Asteroids 最小覆盖数

    http://poj.org/problem?id=3041 题目大意: 一辆宇宙飞船在一个小行星带中,你知道,这很危险.他有一种武器,可以清除掉一行或一列的小行星.问把小行星全部清除最少的武器使用次 ...

  9. 素数表(Eratosthenes)

    怎么判断一个数是素数? 常规的方法是枚举从2开始的数,看看是否能被整除. 但是,如果要判断的数很多的时候,那么效率会十分低下.... 一个优化的方法是不用判断比这个数小的所有数(到平方根位置),而是判 ...

  10. GO语言学习(九)Go 语言运算符

    运算符用于在程序运行时执行数学或逻辑运算. Go 语言内置的运算符有: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 其他运算符 接下来让我们来详细看看各个运算符的介绍. 算术运算符 下表 ...