您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: