HDU 1074 Doing Homework 經典DP

題目鏈接點我

題目大意是小明有很多功課要去做,都要做完,每門課有一個截止時間和做它需要的時間。

注意到數據量是15,這很明顯告訴我們可以枚舉用二進制
對,一開始我還真的沒想出來狀態是什麼
看到數據量後,就以二進制爲狀態
比如7就表示第一門第二門第三門功課做完需要最小的時間

下面貼代碼

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <iostream>
using namespace std;

const int inf = 0x3f3f3f3f;


struct po
{
    char name[101];
    int d,l;
};

po a[50];


struct node
{
    int pre,now,v,time;
};


node dp[(1<<16)];

int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        getchar();
        for(int i=0;i<n;i++){
            scanf("%s %d%d%*c",a[i].name,&a[i].d,&a[i].l);
            //printf("%s %d %d\n",a[i].name,a[i].d,a[i].l);
        }

        for(int i = 1;i<(1<<n);i++){ //枚舉二進制狀態
            dp[i].v = inf;
            for(int j=n-1;j>=0;j--){
                if((i>>j)&1){
                    int past = i-(1<<j);
                    int tt = dp[past].time + a[j].l - a[j].d;
                    if(tt<0) tt=0;
                    if(dp[past].v + tt < dp[i].v){
                        dp[i].v = dp[past].v + tt;
                        dp[i].time = dp[past].time + a[j].l;
                        dp[i].now = j;
                        dp[i].pre = past;
                    }

                }
            }
        }
        printf("%d\n",dp[(1<<n)-1].v);
        int tmp = (1<<n)-1; // 結果要倒過來輸出
        stack<int> S;
        while(tmp){
            S.push(dp[tmp].now);
            tmp = dp[tmp].pre;
        }
        while(!S.empty()){
            int i = S.top();S.pop();
            printf("%s\n",a[i].name);
        }
    }
    return 0;

}

學dp的路還很長,堅持才能逐漸掌握。
畢竟這世界套路太深。

發佈了40 篇原創文章 · 獲贊 7 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章