状态DP Doing Homework HDU - 1074
题目大意: 给出n种作业,每个作业的名字,截止时间和所需的时间,超过截止时间的作业,每超过一天要扣一分,要你合理的安排作业的顺序使得扣掉的分数最少。
思路:一直觉得可以用贪心,然而不对。1代表完成作业,0代表还未完成的作业,枚举所有的状态,推出并更新下一个状态。例如3个作业的话0(000)可以推出 001,010,100这三种状态,而011可以由 001或者010推出,选这两者中的最小值。
http://www.cppblog.com/notonlysuccess/archive/2009/02/18/74168.aspx
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #define inf 0x3f3f3f3f #define maxn 16 using namespace std; typedef struct { string s; int de,c; }P; P a[maxn]; int dp[1<<maxn],pre[1<<maxn],n; void print(int x) { if(x==0) return ; print(pre[x]); int t; for(int i=0;i<n;i++) if((x&(1<<i))!=0&&(pre[x]&(1<<i))==0) t=i; cout<<a[t].s<<endl; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0;i<n;i++) cin>>a[i].s>>a[i].de>>a[i].c; for(int i=1;i<(1<<n);i++) dp[i]=inf; dp[0]=0; for(int i=0;i<(1<<n);i++) { int s=0; for(int k=0;k<n;k++) if(i&(1<<k)) s+=a[k].c; for(int j=0;j<n;j++) { if((i&(1<<j))==0) { int ss=s; ss+=a[j].c; if(ss>a[j].de) ss=ss-a[j].de; else ss=0; if(dp[i|(1<<j)]>dp[i]+ss) { dp[i|(1<<j)]=dp[i]+ss; pre[i|(1<<j)]=i; } } } } printf("%d\n",dp[(1<<n)-1]); print((1<<n)-1); } return 0; }