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

    Doing Homework HDU - 1074

    题意:

    有n个作业,每个作业有一个截止时间和完成所需时间,如果完成某个作业的时间超出了截止时间就扣完成时间-截止时间的分。求按怎样的顺序完成作业扣分最少。

    方法:状压dp。ans[S]表示完成集合S的作业最少的扣分(集合S用一个数字表示)。pre[S]和pre2[S]分别表示由前一个状态到达状态S完成的作业序号、S的前一个状态。

    首先应该意识到完成某个集合的作业,不管按照何顺序,总时间都是一样的。(曾经没发现导致没思路)

    从小到大枚举S(这样的话枚举到每个集合时其去掉某个作业得到的集合保证都已经枚举到过,因为其子集的数字表示一定小于S)。

    $ans[S]=min{ans[S-p]+max(sumt[S]-d[p],0)}$(p表示S集合内任意一项作业)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 using namespace std;
     6 typedef long long LL;
     7 char name[16][110];
     8 LL d[16],c[16],ans[70000];
     9 LL pre[70000],pre2[70000];
    10 LL T,n,sumt;
    11 vector<LL> vec;
    12 int main()
    13 {
    14     LL i,j,t;
    15     scanf("%lld",&T);
    16     while(T--)
    17     {
    18         memset(name,0,sizeof(name));
    19         memset(ans,0x3f,sizeof(ans));
    20         memset(pre,0,sizeof(pre));
    21         memset(pre2,0,sizeof(pre2));
    22         scanf("%lld",&n);
    23         for(i=1;i<=n;i++)
    24             scanf("%s%lld%lld",name[i],&d[i],&c[i]);
    25         ans[0]=0;
    26         for(i=1;i<(1<<n);i++)
    27         {
    28             sumt=0;
    29             for(j=1;j<=n;j++)
    30                 if(i&(1<<(j-1)))
    31                     sumt+=c[j];
    32             for(j=1;j<=n;j++)
    33                 if(i&(1<<(j-1)))
    34                 {
    35                     t=ans[i^(1<<(j-1))]+max(sumt-d[j],0LL);
    36                     if(t<=ans[i])
    37                     {
    38                         ans[i]=t;
    39                         pre[i]=j;
    40                         pre2[i]=i^(1<<(j-1));
    41                     }
    42                 }
    43         }
    44         printf("%lld
    ",ans[(1<<n)-1]);
    45         vec.clear();
    46         for(i=(1<<n)-1;i!=0;i=pre2[i])
    47             vec.push_back(pre[i]);
    48         for(i=vec.size()-1;i>=0;i--)
    49             printf("%s
    ",name[vec[i]]);
    50     }
    51     return 0;
    52 }

    某题解

    一个裸状态压缩~

    题目大意: 一共有N门作业,三个数据是作业的名字,到期时间,和完成需要天数,完成做也期限超过一天扣一分.问以什么顺序完成作业可以使扣得分最少.如果有相同的分数名字按字典序排序.

    状态转移方程: dp[i]=min(dp[j]+hw[k]-hwlast[k])+hw[k];  j为i中去掉第k个作业的状态,hw[k]为当前作业需要几天完成,hwlast为当前作业完成期限为多少,若(dp[j]+hw[k]<hwlast[k])则取零,表示状态不可用.

    源代码:

    #include <myhead.h>
    
    const int N=16;
    const int M=110;
    const int NUM=(1<<N);
    struct HomeWork {
    	char name[M];
    	int last;
    	int time;
    };
    struct Dp {
    	int timer;
    	int scr;
    	int last;
    	int i;
    	void init() {
    		this->timer=0;
    		this->scr=INT_MAX;
    		this->last=0;
    		this->i=0;
    	}
    };
    int n,num;
    HomeWork hw[N];
    Dp dp[NUM];
    
    void init() {
    	scanf("%d",&n);
    	num=(1<<n);
    	dp[0].init();
    	dp[0].scr=0;
    	for(int i=0;i<n;++i) {
    		scanf("%s%d%d",hw[i].name,&hw[i].last,&hw[i].time);
    	}
    }
    
    void work() {
    	for(int i=1;i<num;++i) {
    		dp[i].init();
    		for(int j=n-1;j>=0;--j) {
    			int s=(1<<j);
    			if(s&i) {
    				int past=i-s;
    				int t=dp[past].timer+hw[j].time-hw[j].last;
    				checkmax(t,0);
    				t+=dp[past].scr;
    				if(t<dp[i].scr) {
    					dp[i].scr=t;
    					dp[i].i=j;
    					dp[i].last=past;
    					dp[i].timer=dp[past].timer+hw[j].time;
    				}
    			}
    		}
    	}
    	stack<int> s;
    	int star=num-1;
    	while(star) {
    		s.push(dp[star].i);
    		star=dp[star].last;
    	}
    	printf("%d
    ",dp[num-1].scr);
    	while(!s.empty()) {
    		printf("%s
    ",hw[s.top()].name);
    		s.pop();
    	}
    }
    
    int main() {
    	int t;
    	scanf("%d",&t);
    	while(t--) {
    		init();
    		work();
    	}
    	return 0;
    }


  • 相关阅读:
    java.sql.SQLException: 数据大小超出此类型的最大值
    日志收集系统 ELK
    centos下mysql 数据库安装、调试
    Log4j应用
    使用webuploader实现大文件断点续传(前端部分)
    es6学习 -- 解构赋值
    es6学习 -- let和const
    关于禁止页面滚动的实践(禁止滚轮事件)
    匿名函数与闭包
    JS高级学习总结--面向对象
  • 原文地址:https://www.cnblogs.com/hehe54321/p/hdu-1074.html
Copyright © 2011-2022 走看看