HDU1074 Doing Homework (状压dp,从n!种排列中选一种排列)

题意

有n个任务,每个任务有一个截止时间,超过截止时间一天,要扣一个分。
求如何安排任务,使得扣的分数最少。

解题

n个任务,共有n!种执行方式。因为n不超过15,所以用状态压缩的方式来表示状态(即二进制)。
设dp[s]表示以状态s作为终止状态的安排方式的所扣最少分数。
状态转移方程:dp[s]=min{dp[s],dp[last]+执行x任务所需时间},状态last与s差了一个任务x。
因为要求在所扣分数相同的情况下,输出字典序最小的方案。所以,枚举状态last(通过枚举任务x来实现)需要排序枚举x任务。

AC代码

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <stack>
#define INF 0x3f3f3f3f
using namespace std;

const int maxn=20;
struct node
{
    string str;
    int ed,t;
    node(string str,int ed,int t):str(str),ed(ed),t(t){}
    node(){}
}a[maxn];
struct state
{
    int sum;//已扣分数
    int time;//当前时间
    int pre;//上一个状态
    int key;
}b[1<<maxn];

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n,cnt=0;
        cin>>n;
        for(int i=0;i<n;i++)
        {
            string str;
            int ed,t;
            cin>>str>>ed>>t;
            a[cnt++]=node(str,ed,t);
        }
        int tar=(1<<n)-1;
        for(int s=1;s<=tar;s++)
        {
            b[s].sum=INF;
            for(int i=n-1;i>=0;i--)//因为时间相等,按任务名字字典序排序
            {
                int tmp=1<<i;
                b[tmp].pre=0;
                b[tmp].key=i;
                if(s&tmp)
                {
                    int last=s-tmp;
                    int add=b[last].time+a[i].t-a[i].ed;
                    if(add<0) add=0;

                    if(add+b[last].sum<b[s].sum)
                    {
                        b[s].sum=add+b[last].sum;
                        b[s].pre=last;
                        b[s].key=i;
                        b[s].time=b[last].time+a[i].t;
                    }
                }
            }
        }
        int x=tar;
        cout<<b[tar].sum<<endl;
        stack<string> sta;
        while(x)
        {
            int k=b[x].key;
            sta.push(a[k].str);
            x=b[x].pre;
        }
        while(!sta.empty())
        {
            cout<<sta.top()<<endl;
            sta.pop();
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37685156/article/details/81137874
今日推荐