1. 程式人生 > >Hdu 1074Doing Homework(狀壓DP)

Hdu 1074Doing Homework(狀壓DP)

Problem Description
Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce his score of the final test, 1 day for 1 point. And as you know, doing homework always takes a long time. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.

Input
The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
Each test case start with a positive integer N(1<=N<=15) which indicate the number of homework. Then N lines follow. Each line contains a string S(the subject’s name, each string will at most has 100 characters) and two integers D(the deadline of the subject), C(how many days will it take Ignatius to finish this subject’s homework).

Note: All the subject names are given in the alphabet increasing order. So you may process the problem much easier.

Output
For each test case, you should output the smallest total reduced score, then give out the order of the subjects, one subject in a line. If there are more than one orders, you should output the alphabet smallest one.

Sample Input
2
3
Computer 3 3
English 20 1
Math 3 2
3
Computer 3 3
English 6 3
Math 6 3

Sample Output
2
Computer
Math
English
3
Computer
English
Math

題意是要求你完成一寫作業,每份作業都有自己的截止日期和所需時間,如果晚交一天就要扣一分,問做完這些作業最少需要扣幾分,這道題感覺得NP難題,好在作業數量只有16個,可以用狀壓DP進行狀態壓縮,複雜度為O(2^n*n^2),狀壓DP的優化就是對記憶體空間的優化,下面是自己的程式碼:

#include<bits/stdc++.h>
using namespace std;
using LL=int64_t;
const int INF=0x3f3f3f3f;
const int maxn=1<<16;
int dp[maxn],dead[maxn],pre[maxn];
int n;
struct Node {
    string s;
    int cost,dead;
}ans[20];

void print(int num) {
    if(num==0) return ;
    print(pre[num]);
    num-=pre[num];//此時的num為一個i位是1其他位都是0的數,減去以後表示此時做這個作業是最優解
    for(int i=0;i<n;i++) {
        if(num&1<<i) cout<<ans[i].s<<endl;
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--) {
        cin>>n;
        for(int i=0;i<n;i++) cin>>ans[i].s>>ans[i].dead>>ans[i].cost;
        int sum=1<<n;
        for(int i=1;i<sum;i++) dp[i]=INF;
        dp[0]=0;
        memset(dead,0,sizeof(dead));
        memset(pre,0,sizeof(pre));
        for(int i=1;i<sum;i++) {
            for(int j=0;j<n;j++) {
                if((i&1<<j)==0) continue;//如果i對應的j位是0表示沒做這個作業
                int k=i-(1<<j);//表示沒做作業這個的情況
                dead[i]=dead[k]+ans[j].cost;
                int cost=dead[i]>ans[j].dead?dead[i]-ans[j].dead:0;
                if(dp[k]+cost<=dp[i]) {
                    dp[i]=dp[k]+cost;
                    pre[i]=k;
                }
            }
        }
        cout<<dp[sum-1]<<endl;
        print(sum-1);
    }
    return 0;
}

相關推薦

Hdu 1074Doing HomeworkDP

Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher

hdu 1074 Doing HomeworkDP

Doing Homework #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #inclu

HDU 1074 Doing HomeworkDP+記錄路徑

原題地址 Doing Homework Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8336 Accepte

dpHDU 4778 Gems Fight!

ont magic fig urn turn sid several desc ant Gems Fight! Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/O

HDU 6149 Valley Numer IIDP

狀壓dp pac aps 狀態 01背包 using 百度 c++ 由於 題目鏈接 HDU6149 百度之星復賽的題目……比賽的時候並沒有做出來。 由於低點只有15個,所以我們可以考慮狀壓DP。 利用01背包的思想,依次考慮每個低點,然後枚

HDU 1565 方格取數(1) DP

http://acm.hdu.edu.cn/showproblem.php?pid=1565 #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring>

hdu 1565 方格取數dp

給你一個n*n的格子的棋盤,每個格子裡面有一個非負數。  從中取出若干個數,使得任意的兩個數所在的格子沒有公共邊,就是說所取的數所在的2個格子不能相鄰,並且取出的數的和最大。 Input 包括多個測試例項,每個測試例項包括一個整數n 和n*n個非負數(n<=20)

HDU 6006 Engineer Assignmentdp

Engineer Assignment Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1164    Acce

HDU 6321dp

傳送門 題面: Problem C. Dynamic Graph Matching Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others) Total S

SRM709 div1 Xscoregamedp

壓縮 out find 初始 reg max algo pan 是我 題目大意: 給定一個序列a,包含n個數(n<=15),每個數的大小小於等於50 初始時x = 0,讓你每次選a中的一個數y,使得x = x + x^y 問如何安排選擇的次序,使得最終結果最大。

lightoj 1057 - Collecting Golddp

define har ring volume www lightoj cst con continue 題目鏈接:http://www.lightoj.com/volume_showproblem.php?problem=1057 題解:看似有點下記憶話搜索但是由於

dpABC 067 F : Mole and Abandoned Mine

技術分享 cts using sub src oops bit live set Mole decided to live in an abandoned mine. The structure of the mine is represented by a simple

dpUVA - 1252 Twenty Questions

ace code return uva typedef clu http 狀壓 .net 題目地址 讀入二進制數及轉換的方法。 e.g. bitset<16> x;   cin>>x;   cout<<x.to_ulong()<&l

POJ 2288 Islands and Bridgesdp

pen clas tdi pac pre 初始 路徑 nds queue http://poj.org/problem?id=2288 題意: 有n個島嶼,每個島嶼有一個權值V,一條哈密頓路徑C1,C2,...Cn的值為3部分之和: 第1部分,將路徑中每個島嶼的權值累

dpNOI 2001POJ 1185 炮兵陣地

上下 數據 enter 能夠 sam src max spa 參加 司令部的將軍們打算在N*M的網格地圖上部署他們的炮兵部隊。一個N*M的地圖由N行M列組成,地圖的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下圖。在每一格平原地形上最多可以布置一支炮

[luoguP1896] [SCOI2005]互不侵犯KingDP

放置 puts turn true i++ bsp pri += light 傳送門 先預處理出來一行中放置國王的所有情況和每種情況所用的國王個數。 f[i][j][k]表示前i行放j個國王且最後一行的狀態為k的方案數 狀壓DP即可 #include &l

[luoguP2704] 炮兵陣地DP

pro 狀態 blank show char %d har void href 傳送門 可以事先把每一行的所有狀態處理出來,發現每一行的狀態數最多不超過60個 f[i][j][k]表示前i行,第i行為狀態j,第i-1行為狀態k的最優解 #include

[luoguP3694] 邦邦的大合唱站隊/簽到題DP

pac sizeof size 前綴和 for ensure -m open https 傳送門 來自kkk的題解: 70分做法:枚舉每個學校順序,暴力。 100分:狀壓dp。從隊列頭到尾DP, 狀態:f[i]表示i狀態下最小的出列(不一致)的個數。 比如f

[luoguP2831] 憤怒的小鳥DP

狀壓 集合 blank tin 處理 cstring tps www. cpp 傳送門 感覺這題不是很難,但是很惡心。 說一下幾點。 1.預處理出來每兩個點所構成的拋物線能消除的豬的集合。 2.如果兩個點橫坐標相同,則不能構成拋物線 3.a >= 0

刷題總結——bzoj1725dp

數據 void clip esp pos 範圍 -c ble include 題目: 題目描述 Farmer John 新買了一塊長方形的牧場,這塊牧場被劃分成 N 行 M 列(1<=M<=12; 1<=N<=12),每一格都是一塊正方形的土地。