zoukankan      html  css  js  c++  java
  • HDU-1074 Doing Homework

    Doing Homework

    https://vjudge.net/problem/HDU-1074/origin

    前言

    第一次学状压 dp,它的思想和 dp 的思想一致,根据前一个状态来推取后一个状态。

    就像这样 (dp[11_2]=min(dp[10_2],dp[01_2]))

    使用二进制来进行表示状态。

    (000_2) 表示一个物品也没有进行选择

    (001_2 = 0*2^2+0*2^1+1*2^0) 表示选择了第 (1) 个物品

    (011_2 = 0*2^2+1*2^1+1*2^0) 表示选择了第 (1、2) 个物品

    (101_2 = 1*2^2+0*2^1+1*2^0) 表示选择了第 (1、3) 个物品


    进而理解,选择第 (x) 个物品的时候,需要对前面没有选过 (x) 这个物品的状态进行求解最小值,而 (((1<<x)&pos)==0) 表示 (pos) 这个状态没有进行选择物品 (x)

    (((1<<x)|pos)==0) 表示在 (pos) 这个状态的基础上进行选择物品 (x)

    进而对添加该物品的状态进行求最小值。

    (dp[(1<<x)|pos]=min(dp[pos]+val[x]))

    感觉应该可以理解,如果有不理解,希望大佬们在评论区询问。

    (Orz)

    题意:

    (T) 组数据,每个数据有 (n) 个课程。

    对于 (n) 个课程,包含三个属性课程名,作业的截止日期和完成作业需要的天数。

    作业完成情况拖延一天结果就是扣一定分数。

    题解

    通过状压 (dp) 进行求解,

    在枚举状态的时候需要保存它的前一个状态。

    之后使用 (dfs) 进行求出所有解。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    struct node{
    	char s[105];
    	int l,r;
    }num[20];
    int dp[1<<16];
    int pre[1<<16];
    bool cmp(node x,node y){
    	int lx=strlen(x.s);
    	int ly=strlen(y.s);
    	for(int i=0;i<lx&&i<ly;++i){
    		if(x.s[i]==y.s[i]);
    		else return x.s[i]<y.s[i];
    	}
    	return lx<ly;
    }
    void dfs(int pos,int n){
    	if(!pos)return;
    	int x;
    	for(int i=0;i<n;++i){
    		if(((1<<i)&pos)&&!(pre[pos]&(1<<i))){
    			x=i;
    		}
    	}
    	dfs(pre[pos],n);
    	printf("%s
    ",num[x].s);
    }
    int main(){
    	int t;
    	scanf("%d",&t);
    	while(t--){
    		int n;
    		memset(dp,INF,sizeof(dp));
    		scanf("%d",&n);
    		for(int i=0;i<n;++i){
    			scanf("%s%d%d",num[i].s,&num[i].l,&num[i].r);
    		}
    		// sort(num,num+n,cmp);
    		// for(int i=0;i<n;++i)
    		// 	printf("%s
    ",num[i].s);
    		dp[0]=0;
    		for(int i=0;i<(1<<n);++i){
    			for(int j=0;j<n;++j){
    				if((1<<j)&i)continue;
    				int val=num[j].r;
    				for(int k=0;k<n;++k){
    					if((1<<k)&i)
    						val+=num[k].r;
    				}
    				val=val>num[j].l?val-num[j].l:0;
    				if(dp[(1<<j)|i]>dp[i]+val){
    					dp[(1<<j)|i]=dp[i]+val;
    					pre[(1<<j)|i]=i;
    				}
    			}
    		}
    		printf("%d
    ",dp[(1<<n)-1]);
    		dfs((1<<n)-1,n);
    	}
    	return 0;
    }
    

    后记

    这个题好像有点问题诶,题目最后要求的是按字典序进行输出,因为怕 (WA) 预处理了一下所有物品 (A) 了,但是把预处理关了也过了。

    仿佛所有的解只有一个结果不需要进行处理的诶。

    新赛季的开始
  • 相关阅读:
    梯度下降法
    超平面
    感知机模型
    三角不等式
    统计学习方法基本概念
    Kaggle 的注册和使用
    win10 部署 Anaconda
    全概率和贝叶斯公式
    行列式
    伴随矩阵
  • 原文地址:https://www.cnblogs.com/VagrantAC/p/12724177.html
Copyright © 2011-2022 走看看