题意:
给出几个学科的作业、每个作业剩余的时间、完成每个学科作业的时间、如果在剩余时间内不能完成相应作业 就要扣分 延迟一天扣一分 求最小扣分
解析:
把这些作业进行全排列 求出最小扣分即可
但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); } } }