1. 程式人生 > >HDU1074 Doing Homework 狀態壓縮DP

HDU1074 Doing Homework 狀態壓縮DP

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

                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
23Computer 3 3English 20 1Math 3 23Computer 3 3English 6 3Math 6 3  
Sample Output

   
    2ComputerMathEnglish3ComputerEnglishMath
    
     
      Hint
     In the second test case, both Computer->English->Math and Computer->Math->English leads to reduce 3 points, but the word "English" appears earlier than the word "Math", so we choose the first order. That is so-called alphabet order.
    
     
 


 

 

題意:有n門課,每門課有截止時間和完成所需的時間,如果超過規定時間完成,每超過一天就會扣1分,問怎樣安排做作業的順序才能使得所扣的分最小

思路:因為最多隻有15門課程,可以使用二進位制來表示所有完成的狀況

例如5,二進位制位101,代表第一門和第三門完成了,第二門沒有完成,那麼我們可以列舉1~1<<n便可以得出所有的狀態

然後對於每一門而言,其狀態是t = 1<<i,我們看這門在現在的狀態s下是不是完成,可以通過判斷s&t是否為1來得到

當得出t屬於s狀態的時候,我們便可以進行DP了,在DP的時候要記錄路徑,方便之後的輸出

 

 

#include <iostream>#include <string>#include <cstring>#include <stack>#include <algorithm>using namespace std;const int inf = 1<<30;struct node{    string name;    int dead,cost;} a[50];struct kode{    int time,score,pre,now;} dp[1<<15];int main(){    int t,i,j,s,n,end;    cin >> t;    while(t--)    {        memset(dp,0,sizeof(dp));        cin >> n;        for(i = 0; i<n; i++)            cin >> a[i].name >> a[i].dead >> a[i].cost;        end = 1<<n;        for(s =  1; s<end; s++)        {            dp[s].score = inf;            for(i = n-1; i>=0; i--)            {                int tem = 1<<i;                if(s & tem)                {                    int past = s-tem;                    int st = dp[past].time+a[i].cost-a[i].dead;                    if(st<0)                        st = 0;                    if(st+dp[past].score<dp[s].score)                    {                        dp[s].score = st+dp[past].score;                        dp[s].now = i;                        dp[s].pre = past;                        dp[s].time = dp[past].time+a[i].cost;                    }                }            }        }        stack<int> S;        int tem = end-1;        cout << dp[tem].score << endl;        while(tem)        {            S.push(dp[tem].now);            tem = dp[tem].pre;        }        while(!S.empty())        {            cout << a[S.top()].name << endl;            S.pop();        }    }    return 0;}


 

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述