hdu 1074 Doing Homework (状压 + 记录路径)

http://acm.hdu.edu.cn/showproblem.php?pid=1074

Doing Homework

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7316    Accepted Submission(s): 3240


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
   
   
   
   
2 3 Computer 3 3 English 20 1 Math 3 2 3 Computer 3 3 English 6 3 Math 6 3
 

Sample Output
   
   
   
   
2 Computer Math English 3 Computer English Math
 题目大意:
有n门课程,每门课程有个作业。这个作业有个最晚上交时间和完成这门课需要的时间。假如没有按照规定时间完成,每晚一天减少一分。
思路:枚举(1<<n)-1种状态,一共n门课程,对每种课程的状态,判断该课程(1<<i)能否右(1--(1<<n))种状态中的一个状态得到,然后dp记录学习了当前课程所花费的时间,和上一门课程的是哪门

最后DFS回溯输出路径

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define N 20
#define INF 0x3f3f3f3f
#define MOD 2009
#define met(a, b) memset (a, b, sizeof(a))

typedef long long LL;

struct node
{
    char str[N];
    int deadline;///当前这门课程的截止日期
    int cost;///学完当前这门课程所要花费的时间
}stu[N];

struct node1
{
    int time;///学完当前这门课程花费的最少时间
    int score;///学完当前这门课程扣除的最少分数
    int now;///当前学的课程
    int pre;///上一门学的课程
}dp[1<<16];

void Search_path (int n)
{
    if (!n) return;
    Search_path (dp[n].pre);
    printf ("%s\n", stu[dp[n].now].str);
    return;
}

int main ()
{
    int t, n;
    scanf ("%d", &t);

    while (t--)
    {
        met (dp, 0);
        met (stu, 0);

        scanf ("%d", &n);

        for (int i=0; i<n; i++)
            scanf ("%s%d%d", stu[i].str, &stu[i].deadline, &stu[i].cost);

        int Lim = (1<<n)-1;

        for (int i=1; i<=Lim; i++)
        {
            dp[i].score  =INF;
            for (int j=n-1; j>=0; j--)
            {
                if (i & (1<<j))
                {
                    int x = i - (1<<j);

                    int Score = dp[x].time + stu[j].cost - stu[j].deadline;
                    if (Score < 0) Score = 0;

                    if (Score + dp[x].score < dp[i].score)
                    {
                        dp[i].score = Score + dp[x].score;
                        dp[i].time = dp[x].time + stu[j].cost;
                        dp[i].pre = x;
                        dp[i].now = j;
                    }
                }
            }
        }
        printf ("%d\n", dp[Lim].score);
        Search_path (Lim);
    }
    return 0;
}

记忆化搜索

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define N 20
#define INF 0x3f3f3f3f
#define MOD 2009
#define met(a, b) memset (a, b, sizeof(a))

typedef long long LL;

struct node
{
    char str[N];
    int deadline;///当前这门课程的截止日期
    int cost;///学完当前这门课程所要花费的时间
}stu[N];

struct node1
{
    int time;///学完当前这门课程花费的最少时间
    int score;///学完当前这门课程扣除的最少分数
}dp[1<<16];

int n;

void Solve (node1 &A, node1 B, node C)
{
    int Time = B.time + C.cost;
    int Score = B.score + abs(min(C.deadline-Time, 0));

    if (A.score > Score|| (A.score==Score && A.time<Time))
    {
        A.score = Score;
        A.time = Time;
    }
}

node1 DFS (int Sta)
{
    if (dp[Sta].score != -1) return dp[Sta];

    dp[Sta].score = INF;

    for (int i=0; i<n; i++)
    {
        if (Sta & (1<<i))
            Solve (dp[Sta], DFS (Sta-(1<<i)), stu[i]);
    }
    return dp[Sta];
}

bool OK (node1 A, node1 B, node C)
{
    int Time = B.time + C.cost;
    int Score = B.score + abs (min (C.deadline-Time, 0));

    if (A.score == Score && A.time == Time)
        return true;
    return false;
}

void Search_path (int Sta)
{
    if (!Sta) return;
    for (int i=n-1; i>=0; i--)
    {
        if (Sta & (1<<i) && OK (dp[Sta], dp[Sta-(1<<i)], stu[i]))
        {
            Search_path(Sta-(1<<i));
            puts (stu[i].str);
            break;
        }
    }
}

int main ()
{
    int t;
    scanf ("%d", &t);

    while (t--)
    {
        scanf ("%d", &n);
        for (int i=0; i<n; i++)
            scanf ("%s%d%d", stu[i].str, &stu[i].deadline, &stu[i].cost);

        met (dp, -1);
        dp[0].score = dp[0].time = 0;

        node1 A = DFS ((1<<n)-1);
        printf ("%d\n", A.score);

        Search_path((1<<n)-1);
    }
    return 0;
}


你可能感兴趣的:(hdu 1074 Doing Homework (状压 + 记录路径))