zoukankan      html  css  js  c++  java
  • [HDU] 1074 Doing Homework (NP性质的DP,远没有过去的自己写得好了)

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=1074

    方法:设一个数num,科目的数量为n,则将num表示成带有前导0的n位二进制数(num肯定不能超范围),在该二进制数的数位中,从左到有第i个数位是1代表第i门课的作业完成,0代笔没有,如n=4,num=6=0110代表第2和3门的作业完成,

    设置状态转移方程,设F(num,k).Ans为 当完成k门课程,完成的科目是num对应的作业完成情况,这一状态下超期的最少天数。F(num,k).Beyond为 当完成k门课程,完成的科目是num对应的作业完成情况,这一状态已经超期的天数,F(num,k).Used 为 当完成k门课程,完成的科目是num对应的作业完成情况,这一状态已经使用的天数

    F(num,k)=

    {

     

      [

      Ans = Course[i].NeedDays - Course[i].DeadLine > 0 ?Course[i].NeedDays - Course[i].DeadLine :0  ,

      Beyond = Ans,                                              

      

      Used =  Course[i].NeedDays,                                        k==1, num in { 2^k| 1<=k<=n-1) };

      

      Pre = 0,

      

      Mask = num

      ]

      

      [

       Ans = Min(  

               {  

                    F(num1,k-1).Ans +( Course[J].NeedDays +F(num1,k-1).Used- Course[J].DeadLine > 0 ?Course[J].NeedDays+F(num1,k-1).Used - Course[J].DeadLine :0) 

                    |  num1 in {完成的k-1个作业的完成情况对应的状态二进制数} && num可以由num1的一个非1数位,第J位变成1获得 . 

               }      

              ),

        

      Beyond =  Ans,                                                                     

      Used =  Course[j].NeedDays+F(num1,k-1).Used ;这里的num1 和j 为上述Min计算选出的;                    k>1

      

      Pre = F(num1,k-1).Mask ; 这里的num1为上述Min计算选出的;

      Mask = num1 ;这里的num1为上述Min计算选出的;

      ]   

           

    }

     由于字段排序的要求,当判断一个数字状态num1是不是可以由一个已经算出结果的num通过一个非1数位,第J位变成1的到的时候,在找这样的一个第j位的时候,从左往右找即可。因为题目的输入就已经是字典有序的了。

    在输入构造好的最有解的时候,就是纯粹模拟了。

    代码:

    #include <iostream>
    #include <stack>
     
    using namespace std;
    int mi[16] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
    struct Course
    {
    char name[100];
    int deadline;
    int duration;
    };
    struct Status
    {
    	int usedDays;
    	int delayDays;
    	int pre;
    	int mask;
    	Status()
    	{
    		mask=0;
    		delayDays=-1;
    	}
    };
    struct in
    {
    	int nums[7000];
    	int count;
    };
    Course courses[16];
    Status dp[33000][16];
    int main()
    {
        int test=0,n;
        cin>>test;
        while(test>0)
        {
            cin>>n;
            for(int i=1;i<=n;i++)
                cin>>courses[i].name>>courses[i].deadline>>courses[i].duration;
    		for(int i=0;i<33000;i++)
    			for(int j=0;j<16;j++)
    			{
    				dp[i][j].mask=0;
    				dp[i][j].delayDays=8000;
    			}
    		in ins[16];
    		for(int i=1;i<=15;i++)
    			ins[i].count=0;
    		for(int i=1;i<=n;i++)
    		{
    			dp[mi[n-i]][1].usedDays=courses[i].duration;
    			dp[mi[n-i]][1].delayDays= (courses[i].duration >  courses[i].deadline )? (courses[i].duration -  courses[i].deadline):0;
    			dp[mi[n-i]][1].pre=0;
    			dp[mi[n-i]][1].mask=mi[n-i];
    			ins[1].count++;
    			ins[1].nums[ins[1].count]=mi[n-i];
    		}
    		for(int i=2;i<=n;i++)
    		{
    			int value;
    			for(int j=1;j<=ins[i-1].count;j++)
    			{
    				value = ins[i-1].nums[j];
    				for(int k=n;k>=1;k--)
    				{
    					if((value&mi[k-1])==0)
    					{
    						int usedDays =courses[n-k+1].duration + dp[value][i-1].usedDays;
    						int min = usedDays > courses[n-k+1].deadline ? (usedDays - courses[n-k+1].deadline):0;
    						min+=dp[value][i-1].delayDays;
    						if(dp[value+mi[k-1]][i].delayDays==8000)
    						{
    								ins[i].count++;
    								ins[i].nums[ins[i].count]=value+mi[k-1];
    						}
    						if(dp[value+mi[k-1]][i].delayDays==8000 || dp[value+mi[k-1]][i].delayDays>min)
    						{
    							dp[value+mi[k-1]][i].delayDays = min;
    							dp[value+mi[k-1]][i].pre = value;
    							dp[value+mi[k-1]][i].usedDays =usedDays;
    						}
    						dp[value+mi[k-1]][i].mask = value+mi[k-1];
    					}
    				}
    			}
    		}
    		cout<<dp[mi[n]-1][n].delayDays<<endl;
    		Status re  = dp[mi[n]-1][n];
    		 int* sts=new int[n+1];
    		int k=n;
    		while(k>=0)
    		{
    			sts[k]=re.mask;
    			if(k>0)
    				re=dp[re.pre][k-1];
    			k--;
    		}
    		k=0;
    		int t_mask;
    		while(k<=n)
    		{
    			if(k==0)
    				t_mask=sts[k];
    			else
    			{
    				int t = (t_mask^sts[k]);
    				for(int p=0;p<=15;p++)
    				{
    					if(mi[p]==t)
    					{
    						cout<<courses[n-p].name<<endl;
    						break;
    					}
    				}
    				t_mask=sts[k];
    			}
    			k++;
    		}
            test--;
        }
        return 0;
    }
    
  • 相关阅读:
    Java8_Stream_了解
    Java8_方法引用和构造器引用
    Java8_函数式接口
    Java8_表达式语法
    Spring注解
    Spring_IOC笔记
    一台电脑访问另一台电脑上的VMware
    Vmware 新装centos7 ping 百度 出现 unknow host
    Windows下的免安装版MySQL配置
    Springboot2 注解@Import的使用
  • 原文地址:https://www.cnblogs.com/kbyd/p/3232854.html
Copyright © 2011-2022 走看看