hdu 1074动态压缩

这题我一直以为是贪心做的,做了好久找不到规律

看了解题报告,学习了压缩dp,类似dist,{v(i)}=min{v(i)-k},这种NP问题,O(n*2^n),数据给的比较小,其实也只能给15了,直接用2<<15数组表示状态

每个状态,记录最优的pre,now,当然pre(上一个状态量)和now(当前节点值)是有关的,其实可以记录一个,最后递归输出now,有几个重要的过程注释在代码里了

哎,最坑的是,解题报告看那什么,直接记住代码了,最后还记错了=.=,不过还好,debug的时候,算是更加了解过程了,不说了,这周可以恶刷dist了,其实koubin的算法更加类似dist,这个代码和之前的dp接近

//状态压缩,用1111表示4中的取值情况,0000表示都不取,0001表示只取1
//这里dp判断还是比较简单的,类似最短路径的,{V{i}} = min{V{i}-k}(k属于i中的集合)
//这里路径小于0,这条路径损失的分数小于0,作0处理
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <string>

using namespace std;
const int MAXN = (1<<31)-1;
typedef struct{
    string cn;
    int tm;
    int del;
}course;
typedef struct{
    int pre;
    int now;
    int tm;
    int red;
}node;
course a[16];
node dp[1<<15];

void init(){
    dp[0].pre = -1;
    dp[0].now = -1;
    dp[0].red = 0;
    dp[0].tm = 0;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            cin>>a[i].cn;
            scanf("%d%d",&a[i].del,&a[i].tm);
        }
        init();
        int tem = (1<<n)-1;
        for(int i=1;i<=tem;i++){
            dp[i].red = MAXN;
            for(int j=n-1;j>=0;j--){ //因为是按输入顺序字典序增加的,前优先,则前优先;比如0101->->1111,如果0101->1101->1111与0101->0111->1111代价相同,则A优先B
                int s = 1<<j;         //这里我们判断离1111最近的取值,因为A比D先取了,所以D才是最靠近1111,则先取后段才是我们要求的前优先
                if(i&s){
                    int past = i-s;
                    int red = dp[past].tm+a[j].tm-a[j].del;
                    if(red<0)red = 0;
                    if(dp[i].red>dp[past].red+red){
                        dp[i].red = dp[past].red+red;
                        dp[i].now = j;
                        dp[i].pre = past;
                        dp[i].tm = dp[past].tm+a[j].tm;
                    }
                }
            }
        }

        cout<<dp[tem].red<<endl;
        stack <int >s1;

        while(tem){
            s1.push(dp[tem].now);
            tem = dp[tem].pre;
        }
        while(!s1.empty()){
            int tx = s1.top();
            s1.pop();
            cout<<a[tx].cn<<endl;
        }
       // cout<<"debug"<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}

时间: 2024-10-13 02:26:19

hdu 1074动态压缩的相关文章

hdu 1074 状态压缩

http://acm.hdu.edu.cn/showproblem.php?pid=1074 我们可以断定状态的终止态一定是n个数全部选完的情况,那么它的前一个状态是什么呢,一定是剔除任一门课程后的n种状态. 例如 dp[全选了]=min{(dp[除了math都做了]+math的超时天数),(dp[除了computer都做了]+computer的超时天数),(dp[除了english都做了]+english的超时天数)}那么接下来的dp状态依然如此. 好了,接下来,我们该如何去思考了,这个题目共

HDU 1074 状态压缩DP 第一次写 多多指教

给你n个数表示有n门作业,下面n行  每行三个数 分别为学科名 截止时间  需要多久才能完成 如果逾期一天则扣掉一学分, 要你求出完成所有作业而被扣最小的学分, 并将完成作业的顺序输出.(时间相同时 按照单词字典数输出) 学分相同时按照字典数输出   目前对于从n-1到0不是很理解 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<map

Doing Homework HDU - 1074 状态压缩

#include<iostream> #include<cstring> #include<cstdio> #include<string> #include<cmath> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=(1<<15)+5; const int MOD=1e9+7; int dead[20],cost[20]; int dp[MAXN],t[

[2016-03-28][HDU][1074][Doing Homework]

时间:2016-03-28 18:46:36 星期一 题目编号:[2016-03-28][HDU][1074][Doing Homework] 题目大意:给定n门科作业的期限时间和完成耗时,每科每超过一天就扣一份,求最少扣分数 分析:n只有15,二进制枚举,状态压缩,枚举每种科目完成的状态,更新下一个状态,求最小值 #include <cstring> #include <cstdio> using namespace std; const int maxstu = 1 <&

HDU 1074 Doing Homework(状压DP)

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 r

hdu 5398 动态树LCT

GCD Tree Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 415    Accepted Submission(s): 172 Problem Description Teacher Mai has a graph with n vertices numbered from 1 to n. For every edge(u,v),

hdu 5002 (动态树lct)

Tree Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 920    Accepted Submission(s): 388 Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node is a

hdu 5314 动态树

Happy King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 821    Accepted Submission(s): 179 Problem Description There are n cities and n−1 roads in Byteland, and they form a tree. The citie

hdu 5180 状态压缩 dp 打表

hdu 5180 状态压缩 dp 打表 题意: 在n*n的国际象棋中,放置若干个国王和k个车,使得国王之间不互相攻击,车之间不互相攻击,车不可攻击到国王(这并不代表国王不能攻击到车).国王能攻击到它上下左右,左上左下右上右下八个位置的棋子,车可以攻击到同一行或同一列中的棋子,求方案总数对1000000007取模后的值. 限制: 1 <= n <=15; 0 <= k <=15 思路: 状态压缩,dp,打表套打表 打表程序如下: 打表程序1: tab[a][b]表示a*b的棋盘王的放