HDOJ 1074 Doing Homework (状压DP)

来源:互联网 发布:js中的radio length 编辑:程序博客网 时间:2024/05/22 15:07
题意:给出 n 种作业,然后给出每种作业交作业的截至日期,和完成这项任务需要的时间。如果在截至日期后交作业,那么每晚一天就要扣一分。求出扣分最少为多少,并且打印最小扣分完成作业的方案,n <=15。

看一下 n,很小只有15,最开始想的就是暴力打印完成这 15 项作业的所有方案,那么就是 15! ,就明显T了。
那么考虑一下DP,开一个数组,dp[i] ,表示完成 i 种课程的最小扣分,但是还是想不到怎么转移,对于 i 种课程有很多种可能,那么就再加一维,dp[i][j],表示的是完成 i 种课程,并且这 i 种课程分别是 j的二进制。那么就按照状压DP的思路写起走就行了。分别枚举 i ,j,然后再来转移。
然后再来考虑一下打印路径的问题,对于每一个dp[i][j],纪录转移到这个状态的前一个 j ,和新加入的课程,也就是两个前驱,再打印就可以了。
题目要求是要按照字典序来打印,这里没有管字典序的问题也能过,想不通。

#include<stdio.h>#include<algorithm>#include<string>#include<string.h>#include<queue>#include<vector>#include<stack>#include<math.h>#include<map>#include<iostream>using namespace std;#define maxn 100005struct node{    int use;    int time;    int preclass;    int prej;}dp[16][1<<16];struct nnode{    char name[110];    int dead;    int day;}a[20];int n,mask;vector<int> s[20];char ans[20][110];int solve(int x){    int cnt=0;    int dx=x;    while(dx)    {        if(dx%2==1)            cnt++;        dx/=2;    }    return cnt;}int main(){    int t;    for(int i=0;i<(1<<15);i++)    {        int cnt=solve(i);        s[cnt].push_back(i);    }    scanf("%d",&t);    while(t--)    {        memset(dp,0x7f,sizeof(dp));        scanf("%d",&n);        mask=(1<<n)-1;        for(int i=0;i<n;i++)            scanf("%s%d%d",a[i].name,&a[i].dead,&a[i].day);        for(int i=0;i<=mask;i++)            dp[0][i].time=dp[0][i].use=0;        for(int i=1;i<=n;i++)        {            int len=s[i-1].size();            for(int jj=0;jj<len;jj++)            {                int j=s[i-1][jj];                for(int k=0;k<n;k++)                {                    int tmp=(1<<k);                    if((j&tmp)==0)                    {                        int now=(j|tmp);                        int tmptime=dp[i-1][j].time+a[k].day-a[k].dead;                        if(tmptime<=0)                            tmptime=0;                        tmptime+=dp[i-1][j].use;                        if(dp[i][now].use>tmptime)                        {                            dp[i][now].use=tmptime;                            dp[i][now].time=dp[i-1][j].time+a[k].day;                            dp[i][now].prej=j;                            dp[i][now].preclass=k;                        }                    }                }            }        }        printf("%d\n",dp[n][mask].use);        int now=mask;        int cnt=0;        for(int i=n;i>=1;i--)        {            strcpy(ans[i],a[dp[i][now].preclass].name);            now=dp[i][now].prej;        }        for(int i=1;i<=n;i++)            printf("%s\n",ans[i]);    }return 0;}


0 0