HDU 1074 Doing Homework DP 状态压缩
2015-12-13 20:02
387 查看
题意:有N(N<15)个作业要做,如果一门课的作业没做完,超过一天,就要罚一分。问:最少罚多少分?并输出做作业的先后顺序,如果有相同罚分的,输出字典序最小的。
思路:状态压缩。用二进制表示做作业的状态:101表示第一科作业和第3科作业都做了的最少罚分,这个可以由100,001两个状态转移过来。
http://acm.hdu.edu.cn/showproblem.php?pid=1074/********************************************* Problem : HDU 1074 Author : NMfloat InkTime (c) NM . All Rights Reserved . ********************************************/ #include <map> #include <set> #include <queue> #include <cmath> #include <ctime> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #define rep(i,a,b) for(LL i = (a) ; i <= (b) ; i ++) #define rrep(i,a,b) for(LL i = (b) ; i >= (a) ; i --) #define repE(p,u) for(Edge * p = G[u].first ; p ; p = p -> next) #define cls(a,x) memset(a,x,sizeof(a)) #define eps 1e-8 using namespace std; typedef long long LL; typedef unsigned long long ULL; LL T,n,m,k; struct Node { char name[105]; LL dt,ot; }t[16]; struct NODE{ LL route[16] ; LL use ; LL cost ; }dp[(1<<15)+5]; LL root[(1<<15)+5]; void init() { LL tmp; rep(i,1,1<<15) { tmp = i; while(tmp) { if(tmp&1) root[i] ++; tmp >>= 1; } } } void input() { scanf("%d",&n); rep(i,1,n) { scanf("%s %d %d",t[i].name,&t[i].dt,&t[i].ot); } } void solve() { rep(i,1,1<<15) dp[i].cost = (LL)1e50; rep(i,1,n) { dp[1<<(i-1)].use = t[i].ot; dp[1<<(i-1)].cost = t[i].ot > t[i].dt ? t[i].ot - t[i].dt : 0; dp[1<<(i-1)].route[1] = i; } LL newcost ; rep(i,2,n) { rep(j,1,(1<<n)-1) { if(root[j] == i) { rrep(ia,0,n-1) { if((1<<ia)&j) { newcost = (t[ia+1].ot + dp[j-(1<<ia)].use) > t[ia+1].dt ? (t[ia+1].ot + dp[j-(1<<ia)].use - t[ia+1].dt) : 0; newcost += dp[j-(1<<ia)].cost ; //printf("i : %d j : %d ia : %d newcost : %d\n",i,j,ia,newcost); if(newcost < dp[j].cost) { dp[j].cost = newcost; rep(ib,1,i-1) dp[j].route[ib] = dp[j-(1<<ia)].route[ib]; dp[j].route[i] = ia + 1; dp[j].use = t[ia+1].ot + dp[j-(1<<ia)].use; } } } } } } printf("%d\n",dp[(1<<n)-1].cost); rep(i,1,n) { //printf("%d\n",dp[(1<<n)-1].route[i]); printf("%s\n",t[dp[(1<<n)-1].route[i]].name); } } int main(void) { //freopen("a.in","r",stdin); init(); scanf("%d",&T); while(T--) { //while(~scanf("%d %d",&n,&m)) { //while(scanf("%d",&n),n) { input(); solve(); } return 0; }
相关文章推荐
- poj-1581
- 《剑指offer》——链表中环的入口结点
- Swift版本UIWebView长按保存图片
- 书面采访
- Apache conf文件配置个人总结
- codeforces 242E. XOR on Segment 线段树
- eclipse-PyDev和vim简易配置
- 第一眼你能看出这是函数声明吗
- 回溯算法---重点
- Effective C++规定45 附加代码
- 移动页面缩放方法之(三)rem布局
- 第一篇
- 自定义不等高cell的纯代码步骤(frame)
- ListView实现单选(一)
- 真机测试时出现 could not find developer disk image问题
- HDU 1176 免费馅饼
- jQuery之call()方法的使用
- Firefox 的页面缩放选项在这里 - Http Tool 插件查看自动格式化后的 json
- 传统金融和互联网金融
- 关键字const在指针中的运用