• HDU 1074 Doing Homework DP 状压DP


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

      题目描述: 给你所有课程的截止时间和工作时长, 一次只能做一种作业, 问最少罚时几天 N <= 15

      解题思路: 由于N很小, 所以第一反应就是状压DP, 我们可以用一个15位二进制数来表示各个课程做完还是没做完, 然后从 S 从 1 到 1 << N 枚举 i 从 1 到 N 枚举, 如果S & (1<<i) 有效则说明i 属于情况 S, 这样我们从上一步S - 1 << i 转移过来就可以, 记录路径就是每当出现答案的更新就将此时的状态和当前处理的位数记住, 压入栈中, 最后再倒着打出来

      代码: 

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <map>
    #include <cstring>
    #include <iterator>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <deque>
    #include <set>
    #include <iterator>
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    using namespace std;
    
    const int maxn = 20;
    int deadline[maxn];
    int cost[maxn];
    string name[maxn];
    const int INF = 0x3fffffff;
    set<string> ans;
    struct node {
        int time, score, pre, now;
    };
    node dp[1<<15];
    set<string>::iterator it;
    
    int main() {
        int t;
        cin >> t;
        while( t-- ) {
            ans.clear();
            memset(dp, 0, sizeof(dp));
            int n;
            cin >> n;
            for( int i = 0; i < n; i++ ) {
                cin >> name[i] >> deadline[i] >> cost[i];
            }
            int end = 1 << (n);
    //        cout << end << endl;
            for( int s = 1; s < end; s++ ) {
                dp[s].score = INF;
                for( int i = n-1; i >= 0; i-- ) {
                    int temp = 1 << i;
                    if( temp & s ) {
                        int past = s- temp;
                        int st = dp[past].time + cost[i] - deadline[i];
                        if( st < 0 ) st = 0;
                        if( st + dp[past].score <  dp[s].score ) {
                            dp[s].score = st + dp[past].score;
                            dp[s].pre = past;
                            dp[s].now = i;
                            dp[s].time = dp[past].time + cost[i];
                        }
                    }
                }
            }
    
            stack<int> S;
            int tem = end-1;
            cout << dp[tem].score << endl;
            while(tem)
            {
                S.push(dp[tem].now);
                tem = dp[tem].pre;
            }
            while(!S.empty())
            {
                cout << name[S.top()] << endl;
                S.pop();
            }
        }
        return 0;
    }
    View Code

      思考: 自己一开始只知道是状压DP, 具体该怎么做还是不知道, 要接触各种DP

  • 相关阅读:
    ISEX安全期计算 V4.0 多国语言版女性安全期避孕计算实用工具软件
    FireARP防火墙 V3.1防局域网ARP攻击的软件
    asp.net页面字段绑定概述
    C# 删除、遍历指定目录下的所有指定文件、文件夹
    加入收藏、设为首页常用脚本
    分页加载数据Demo
    学习fragment的生命周期
    widget控件
    Menu菜单的代码和xml的创建
    WebView控件
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/7340616.html
Copyright © 2020-2023  润新知