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;
}


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