• HDU 1074—压缩DP


    第一次写博客,感觉第一次理解dp一些,(写成了记忆化搜索,现在想想递推也不难理解)

    HDU 1074,

    题意是安排做作业顺序,这里的压缩状态,0不做,1做了,然后搜索下一状态,类似广度搜索,然和比较可以到这一状态的最优解,这里类似记忆化搜索一样保存所有搜过的状态,(可能dp就是一种特殊的记忆化搜索?)

    下面见代码

    #include <iostream>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <string>
    #include <cstring>
    using namespace std;
    
    int dp[1<<16];
    int arr[1<<16];
    int vis[1<<16];
    string as[1<<16];
    char s[15][100];
    int dead[15];
    int many[15];
    int n;
    
    void solve(){
    
        queue<int> q;
        q.push(0);
        vis[0]=1;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            for(int i=0;i<n;i++){
                //下一状态
                int xx=(x|(1<<i));
                //如果没有解决,找解决方案
                if(vis[xx]==0){
                    for(int j=0;j<n;j++){
                        if((xx>>j)%2==1){
                            int yy=(~((~xx)|(1<<j)));
                            int jia=dead[j]-arr[yy]-many[j];
                            if(jia>0)
                                jia=0;
                            if(dp[xx]<dp[yy]+jia){
                                dp[xx]=dp[yy]+jia;
                                arr[xx]=arr[yy]+many[j];
                                as[xx]=as[yy]+'
    '+(string)s[j];
                            }
                            else if(dp[xx]==dp[yy]+jia){
                                arr[xx]=arr[yy]+many[j];
                                as[xx]=as[yy]+'
    '+(string)s[j];
                            }
                        }
                    }
                    q.push(xx);
                    vis[xx]=1;
                }
                else{
                    continue;
                }
            }
        }
    
    }
    
    int main()
    {
        int t;
        cin>>t;
        while(t--){
            scanf("%d",&n);
            memset(arr,0,sizeof(arr));
            memset(vis,0,sizeof(vis));
            //memset(dp,0,sizeof(dp));
            for(int i=0;i<(1<<n);i++){
                dp[i]=-999999;
            }
            for(int i=0;i<n;i++){
                scanf("%s %d %d",s[i],&dead[i],&many[i]);
            }
            dp[0]=0;
            arr[0]=0;
            solve();
            cout<<-dp[(1<<n)-1]<<endl;
            cout<<as[(1<<n)-1].substr(1,as[(1<<n)-1].size())<<endl;
        }
    }
    


    代码写的很丑也没有优化,小白的学习之路,加油

  • 相关阅读:
    Codeforces 514C Watto and Mechanism(字典树)
    计蒜客 直线的交点(计算几何 + 逆序对)
    Codeforces 837D Round Subset(背包)
    计蒜客 商汤科技的行人检测(随机化+计算几何)
    HDU 5893 List wants to travel(树链剖分+线段树)
    操作系统的中断处理
    Linux 安装 webmin
    Fedora 安装 phpMyAdmin(可能只有自己看得懂)
    httpd编译安装php
    IA-32e架构下的内核初始化内存管理
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672599.html
Copyright © 2020-2023  润新知