• HDU 1074 Doing Homework (状态压缩DP)


    Doing Homework

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 3595    Accepted Submission(s): 1424


    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 reduce his score of the final test, 1 day for 1 point. And as you know, doing homework always takes a long time. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.
     
    Input
    The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
    Each test case start with a positive integer N(1<=N<=15) which indicate the number of homework. Then N lines follow. Each line contains a string S(the subject's name, each string will at most has 100 characters) and two integers D(the deadline of the subject), C(how many days will it take Ignatius to finish this subject's homework). 

    Note: All the subject names are given in the alphabet increasing order. So you may process the problem much easier.
     
    Output
    For each test case, you should output the smallest total reduced score, then give out the order of the subjects, one subject in a line. If there are more than one orders, you should output the alphabet smallest one.
     
    Sample Input
    2 3 Computer 3 3 English 20 1 Math 3 2 3 Computer 3 3 English 6 3 Math 6 3
     
    Sample Output
    2 Computer Math English 3 Computer English Math
    Hint
    In the second test case, both Computer->English->Math and Computer->Math->English leads to reduce 3 points, but the word "English" appears earlier than the word "Math", so we choose the first order. That is so-called alphabet order.
     
    Author
    Ignatius.L
    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #define N (1<<15)+5
    #define M 120
    #define INF 0x3f3f3f3f
    using namespace std;
    int dp[N];//dp[i]表示状态i时最少扣的分数
    struct node
    {
    	char name[M];
    	int d,c;//截止日期,花费时间       
    }a[20];
    int path[N];//path[i]=k表示i状态是由k状态转移过来的
    int t,n;
    /*
    打印路径就是在状态转移的时候用一个数组记录下来,一个状态是由哪一个状态成功转移过来的,然后最后打印路径的时候就是反着这个根据用递归输出出来就行了
    */
    void print(int x)
    {
    	if(x==0)
    		return;
    	int t=0;
    	for(int i=0;i<n;i++)
    	{
    		if( (x&(1<<i)) !=0 && (path[x]&(1<<i)) ==0 )//有这个状态有交际,并且能补全上一个状态
    		{
    			t=i;
    			break;
    		}	
    	}
    	print(path[x]);
    	printf("%s
    ",a[t].name);
    }
    /*
    状态的转移:先枚举二进制的状态,每枚举到一个状态的时候,在这个状态中遍历所有课程,若这门课程完成了那么已经包括在这个状态中了,如果没完成就要
    像01背包那样讨论完成和不完成的罚时到底哪个小,假如现在不完成的罚时小,那么这门课就先不完成,后面在完成。
    */
    int main()
    {
    	//freopen("in.txt", "r", stdin);
    	scanf("%d",&t);
    	while(t--)
    	{
    		scanf("%d
    ",&n);
    		for(int i=0;i<n;i++)
    			scanf("%s %d %d
    ",&a[i].name,&a[i].d,&a[i].c);
    		memset(dp,INF,sizeof dp);
    		memset(path,0,sizeof path);
    		dp[0]=0;//什么课也没开始上罚时当然是0了
    		int tol=(1<<n);
    		for(int i=0;i<tol;i++)//枚举状态
    		{
    			for(int j=n-1;j>=0;j--)//枚举那门课
    			{
    				if((i&(1<<j))==0)//这门课上没上,找出每一个当前功课没完成的状态,然后由这个状态转移到完成了当前课程的状态
    				{
    					int s=0;
    					for(int k=0;k<n;k++)//计算这个状态到现在花费的时间
    						if(i&(1<<k))//这门课上了
    						s+=a[k].c;
    					s+=a[j].c;//再加上j这门课花费的时间
    					int time=s-a[j].d;//计算罚时
    					if(time<0)
    						time=0;
    					if(dp[i|(1<<j)]>dp[i]+time)
    					{
    						dp[i|(1<<j)]=dp[i]+time;
    						path[i|(1<<j)]=i;//如果这个状态转移过来了,就记录下来是由哪个状态转移过来的
    					}	
    					//cout<<dp[i|(1<<j)]<<endl;
    				}
    			}
    		}
    		//for(int i=0;i<tol;i++)
    		//	cout<<path[i]<<" ";
    		//cout<<endl;
    		printf("%d
    ",dp[tol-1]);
    		print(tol-1);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    在提交订单时,为了让用户体验更好,一般改成正在提交,后面加三个点,为了让页面更生动,可以把点点改成动态
    js日期格式化
    h5嵌入视频遇到的bug及总结---转载
    字符串中删除多个特定的字符串
    在苹果手机上input有内阴影怎么去除
    把彩色图片置灰色图片
    springmvc入门程序
    Linux常用命令大全
    MyBatis逆向工程详细教程
    MyBatis整合Spring详细教程
  • 原文地址:https://www.cnblogs.com/wuwangchuxin0924/p/5741126.html
Copyright © 2020-2023  润新知