Doing Homework---hdu1074(状态压缩&&记忆化搜索)

Posted 西瓜不懂柠檬的酸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Doing Homework---hdu1074(状态压缩&&记忆化搜索)相关的知识,希望对你有一定的参考价值。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1074

 

有n(n<=15)门课需要做作业,每门课所需时间是used_time以及每门课作业上交的最后期限是deadline,晚交一天扣一分,现在来安排最好的写作业计划,让最终的扣除分数最少;
 
由于n的取值范围不大所以我们可以枚举除所有的状态进行判断是否是最优的即可,状态数为2^n-1;
我们可以用状态压缩来表示出各种状态;二进制中的第i为为1代表第i门课已经完成了。
 
技术分享
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

#define N 1050
#define MOD 1000000007
#define met(a, b) memset(a, b, sizeof(a))
#define INF 0x3f3f3f3f

typedef long long LL;

int n, pre[N];

struct course
{
    char name[220];
    int deadline, use_time;
} Course[20];

struct Status
{
    int scores;///当前状态能扣除的最少分数;
    int times;///当前状态所需的总时间;
} dp[1<<16];

void solve(Status& A, Status B, course C)///更新dp;
{
    int Times = B.times + C.use_time;

    int Score = B.scores + max(Times - C.deadline, 0);

    if( A.scores > Score || ( A.scores == Score && A.times > Times ))
    {
        A.scores = Score;
        A.times = Times;
    }
}

Status dfs(int sta)
{
    if( dp[sta].scores != -1 )///记忆化搜索就是防止一个状态被重复搜索,所以要更新dp的值;
        return dp[sta];

    dp[sta].scores = INF;

    for(int i=0; i<n; i++)
    {
        if( sta & (1<<i) )///表示当前状态第i门课已经完成了。所以我们要找达到这种状态的其他状态;
            solve(dp[sta], dfs(sta-(1<<i)), Course[i]);///sta的状态是由sta-(1<<i)加上第i门课得到的;
    }
    return dp[sta];
}

bool Judge(Status A, Status B, course C)
{
    int Times = B.times + C.use_time;

    int Score = B.scores + max(Times - C.deadline, 0);

    return A.scores == Score && A.times == Times;
}

void Puts_Path(int sta)
{
    if(sta == 0) return ;

    for(int i=n-1; i>=0; i--)
    {
        if( sta&(1<<i) && Judge(dp[sta], dp[sta-(1<<i)], Course[i]) )///判断当前的状态dp[sta]值是不是由dp[sta-(1<<i)]和Course得到;
        {
            Puts_Path( sta-(1<<i) );
            printf("%s\n", Course[i].name);///路径是倒着找的的所以应在回溯的过程输出
            break;
        }
    }

}


int main()
{
    int T;

    scanf("%d", &T);

    while(T--)
    {
        met(dp, -1);

        met(Course, 0);

        scanf("%d", &n);

        for(int i=0; i<n; i++)
            scanf("%s %d %d", Course[i].name, &Course[i].deadline, &Course[i].use_time);

        dp[0].scores = dp[0].times = 0;

        Status ans = dfs( (1<<n) - 1 );///从最后一个状态开始找;

        printf("%d\n", ans.scores);

        Puts_Path( (1<<n) - 1 );///输出路径;
    }
    return 0;
}
记忆化搜索

 

以上是关于Doing Homework---hdu1074(状态压缩&&记忆化搜索)的主要内容,如果未能解决你的问题,请参考以下文章

[kuangbin带你飞]专题1-23 Doing Homework HDU - 1074

[kuangbin带你飞]专题1-23 Doing Homework HDU - 1074

Doing Homework HDU - 1074 状态压缩

Doing Homework HDU - 1074

Doing Homework HDU - 1074

Doing Homework---hdu1074(状态压缩&&记忆化搜索)