题意:有n个作业,有截止日期和需要完成的时间,超出期限一天就扣一分。问最少扣多少分
思路:因为最多15门课,而15!太大了,所以进行状压,而2^15只有3w多,所以是可以进行的,状压后,把每种情况都枚举一下,然后同时进行时间和分数的dp,最后把分数都转移到bit-1,虽然我懂了是怎样状压dp的,但我不知道是怎么打印出来的,只知道是类似于用并查集维护一样,我打印了并查集数据也没看出来,还是不行呐
代码:
#include <bits/stdc++.h> using namespace std; const int maxn=(1<<15)+7; const int inf=0x3f3f3f3f; int n,dp[maxn],t[maxn],dea[maxn],fin[maxn],fa[maxn]; char s[20][15]; void solve(int x) { if(!x)return ; solve(x-(1<<fa[x])); printf("%s\n",s[fa[x]]); } int main() { int T; scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s%d%d",&s[i],&dea[i],&fin[i]); } int bit=1<<n; for(int i=1;i<bit;i++){ dp[i]=inf; for(int j=n-1;j>=0;j--){ int temp=1<<j; if(!(i&temp))continue; int ans=t[i-temp]+fin[j]-dea[j]; if(ans<0) ans=0; if(dp[i]>dp[i-temp]+ans){ dp[i]=dp[i-temp]+ans; t[i]=t[i-temp]+fin[j]; fa[i]=j; } } } // for(int i=0;i<bit;i++){ // printf("fa[%d] == %d\n",i,fa[i]); // } printf("%d\n",dp[bit-1]); solve(bit-1); } return 0; }