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

记忆化搜索

时间: 2024-10-12 16:08:41

Doing Homework---hdu1074(状态压缩&&记忆化搜索)的相关文章

ACM学习历程—ZOJ3471 Most Powerful(dp &amp;&amp; 状态压缩 &amp;&amp; 记忆化搜索 &amp;&amp; 位运算)

Description Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way

UVA 11008--Antimatter Ray Clearcutting+状态压缩记忆化搜索

题目链接:点击进入 最多只有16个点,如果不用状态压缩的话,最优子结构没法找到.所以我们进行状态压缩,用一个数表示当前的状态,对应二进制位为1表示该位置的树还未被砍掉,为0表示已被砍掉,初始状态为(1< #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn 20 #define INF 0x3f3f3f3f typedef struct { i

状压DP+记忆化搜索 UVA 1252 Twenty Questions

题目传送门 1 /* 2 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 3 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 4 若和答案(自己拟定)相差小于等于1时,证说明已经能区分了,回溯.否则还要加问题再询问 5 */ 6 /************************************************ 7 * Author :Running_Time 8 * Created Time :

ACM-ICPC 2018 徐州赛区网络预赛 B BE, GE or NE(博弈,记忆化搜索)

链接https://nanti.jisuanke.com/t/31454 思路 开始没读懂题,也没注意看数据范围(1000*200的状态,记忆化搜索随便搞) 用记忆化搜索处理出来每个状态的胜负情况 因为每个人都会选择最优的,因此记忆化搜索的过程其实就是在模拟两个人每一步决策所带来的胜负情况, 只要返回一个必胜,就直接返回(因为会选择最优) 然后在没有返回必胜的状态下,有平局就选择平局,没有平局就只能输了 #include<bits/stdc++.h> #define st 100 #defin

UVa 1252 - Twenty Questions(记忆化搜索,状态压缩dp)

题目链接:uva 1252 题意: 有n个长度为m的二进制串,每个都是不同的. 为了把所有字符串区分开,你可以询问,每次可以问某位上是0还是1. 问最少提问次数,可以把所有字符串区分开来. 思路来源于:点击打开链接 思路: m很小,可以考虑状态压缩. dp[s1][s2]表示询问的状态为s1时,此时能猜到状态包含s2时最小需要的步数. 当询问的几位=s2的二进制串小于2时就能区分出来了,dp[s1][s2]=0: 不能区分则再询问一次,s1|=(1<<k),如果问某位为0,则s2不变,问某位为

hdu 4628 Pieces(状态压缩+记忆化搜索)

Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1811    Accepted Submission(s): 932 Problem Description You heart broke into pieces.My string broke into pieces.But you will recover one

hdu4753 状态压缩dp博弈(记忆化搜索写法)

http://acm.hdu.edu.cn/showproblem.php?pid=4753 Problem Description There is a 3 by 3 grid and each vertex is assigned a number. It looks like JiuGongGe, but they are different, for we are not going to fill the cell but the edge. For instance, adding

vijos - P1456最小总代价 (状态压缩DP + 记忆化搜索)

P1456最小总代价 Accepted 标签:[显示标签] 描述 n个人在做传递物品的游戏,编号为1-n. 游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位:下一个人可以传递给未接过物品的任意一人. 即物品只能经过同一个人一次,而且每次传递过程都有一个代价:不同的人传给不同的人的代价值之间没有联系: 求当物品经过所有n个人后,整个过程的总代价是多少. 格式 输入格式 第一行为n,表示共有n个人(16>=n>=2): 以下为n*n的矩阵,第i+1行.第j列表示物

POJ 1351 Number of Locks (记忆化搜索 状态压缩)

Number of Locks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1161   Accepted: 571 Description In certain factory a kind of spring locks is manufactured. There are n slots (1 < n < 17, n is a natural number.) for each lock. The height