题意:n个作业,每个作业有deadline和做完这个作业需要花的时间cost,完成作业每超过一天就减一分,求减去的最小的分数
分析:作业的全排列中取最优解,但是15!太大了会超时,所以用二进制来状态压缩,15个二进制位,第i位的0/1代表第i个作业是否完成。
1.会用状态压缩
2.保存和输出最优解序列方法
慢慢加深理解吧
代码:
#include<iostream> #include<cstring> #include<string> #define INF 1<<16 using namespace std; int t,n; struct node1{ string chr; int ddl,cost; }a[16]; struct node2{ int pre,reduced,days; }dp[INF]; int vis[INF]; void Output(int i) { int tmp=dp[i].pre^i; int cnt=0; tmp>>=1; while(tmp){ cnt++; tmp>>=1; } if(dp[i].pre!=0) Output(dp[i].pre); cout<<a[cnt].chr<<endl; } int main() { cin>>t; while(t--){ memset(vis,0,sizeof(vis)); cin>>n; for(int i=0;i<n;i++) cin>>a[i].chr>>a[i].ddl>>a[i].cost; dp[0].pre=-1,dp[0].days=0,dp[0].reduced=0; vis[0]=1; int en=(1<<n)-1; for(int i=0;i<en;i++){ for(int j=0;j<n;j++){ int tmp=1<<j; if((i&tmp)==0){ int tmp2=i|tmp; int day=dp[i].days+a[j].cost; dp[tmp2].days=day; int reduce=day-a[j].ddl; if(reduce<0) reduce=0; reduce+=dp[i].reduced; if(vis[tmp2]){ if(reduce<dp[tmp2].reduced){ dp[tmp2].reduced=reduce; dp[tmp2].pre=i; } } else{ vis[tmp2]=1; dp[tmp2].reduced=reduce; dp[tmp2].pre=i; } } } } cout<<dp[en].reduced<<endl; Output(en); } }
时间: 2024-10-21 05:19:25