hdu 1074 (状压dp)

题意:

给出几个学科的作业、每个作业剩余的时间、完成每个学科作业的时间、如果在剩余时间内不能完成相应作业 就要扣分 延迟一天扣一分 求最小扣分

解析:

把这些作业进行全排列  求出最小扣分即可  

但A(15,15) 情况这么多  自然要想到状态压缩  1表示已经做完  0表示还没有做

用dp存储最小扣分   pre存储得到最小分的路径 (即做作业的顺序) 

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;

public class Main{
    final static int maxn = 1<<16;
    final static int INF = 0xfffffff;
    public static int n;
    public static class node{
        String name = new String();
        int d,c;
        node(String name, int d, int c)
        {
            this.name = name;
            this.d = d;
            this.c = c;
        }
    } 
    public static ArrayList<node> list = new ArrayList<>();
    public static int[] pre = new int[maxn];
    public static void  print(int step)        //输出函数  类似 bfs最短路输出路径
    {
        if(step == 0)
            return;
        int t = 0;
        for(int i=0;i<n;i++)
        {
            if((step & (1<<i)) != 0 && (pre[step] & (1<<i)) == 0)
            {
                t = i;
                break;
            }
        }
        print(pre[step]);
        System.out.println(list.get(t).name);
    }
    public static void main(String[] args)  {
        Scanner cin = new Scanner(System.in);
        int cnt = 0;
        int T = cin.nextInt();
        while(T-- != 0)
        {
            list.clear();
            int[] dp = new int[maxn];
            Arrays.fill(pre, 0);
            n = cin.nextInt();
            for(int i=0;i<n;i++)
            {
                String name = cin.next();
                int d = cin.nextInt();
                int c = cin.nextInt();
                list.add(new node(name,d,c));
            }
            Arrays.fill(dp, INF);
            dp[0] = 0;
            for(int i=0;i < 1<<n;i++)  //已经做完的作业
            {
                for(int j=0;j<n;j++)    // 即将要做的作业
                {
                    if((i & (1<<j)) != 0) continue;   
                    int s = 0;
                    for(int k=0;k<n;k++)    //求出已经做完的作业的所耗费的时间  
                    {
                        if((i & (1<<k)) != 0)
                        {
                            s += list.get(k).c;
                        }
                    }
                    if(s + list.get(j).c > list.get(j).d)   //求出即将要做的作业是否超时
                        s = s + list.get(j).c - list.get(j).d;
                    else
                        s = 0;
                    if(dp[i|(1<<j)] > dp[i] + s)   
                    {
                        dp[i|(1<<j)] = dp[i] + s;
                        pre[i|(1<<j)] = i;
                    }
                }
            }
            System.out.println(dp[(1<<n)-1]);
            print((1<<n)-1);
    
        }

    }
}

猜你喜欢

转载自www.cnblogs.com/WTSRUVF/p/9064367.html