hdu 1074

題意:有n門功課,每一門需要c天完成,若在d天還沒有完成,之後每一天直到完成,會被扣分數。

一題dp。

用的狀態壓縮,因爲最多15門功課。所以我們可以從1枚舉到1<<15 - 1來代表所有功課的完成情況。比如有三門功課101代表,第一門和第三門完成,而第二門沒有完成。

用&判斷此功課是否在當前枚舉量中存在,若存在,便可尋求當前的最優解和跟新父節點。

每一次狀態的改變都是在枚舉量變化之後,所以從前開始改變功課當前的狀態,還是從後開始,並不影響答案。

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn = 15 + 5;
const int inf = 100000000;
struct node
{
    string name;
    int dead;
    int cost;
}work[maxn];
struct node1
{
    int pre, time, cost, now;
}dp[1<<15 + 5];
void print(int n)
{
    if(dp[n].pre) print(dp[n].pre);
    cout<<work[dp[n].now].name<<endl;
}
int main()
{
    int T;
    scanf("%d", &T);
    for(int kase = 1; kase <= T; kase++)
    {
        int n;
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
        {
            cin>>work[i].name>>work[i].dead>>work[i].cost;
        }
        int tot = 1<<n;
        dp[0].time = 0;
        dp[0].cost = 0;
        for(int i = 1; i < tot; i++)
        {
            dp[i].pre = 0;
            dp[i].cost = inf;
            for(int s = n -1; s >= 0; s--)
            {
                if(i & (1<<s))
                {
                   // printf("%d %d\n", i, s);
                    int past = i - (1<<s);
                    int waste = dp[past].time + work[s].cost - work[s].dead;
                    if(waste < 0)
                        waste = 0;
                    //printf("%d %d\n", past, dp[past].cost);
                    if(dp[i].cost > dp[past].cost + waste)
                    {
                        //printf("%d %d\n", i, waste);
                        dp[i].cost = dp[past].cost + waste;//更新扣分次數
                        dp[i].time = work[s].cost + dp[past].time;//更新此狀態的天數
                        dp[i].pre = past;
                        dp[i].now = s;
                    }
                }
            }
        }
        printf("%d\n", dp[tot - 1].cost);
        print(tot - 1);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章