HDU-1074-状态压缩DP

https://cn.vjudge.net/contest/165707#problem/D
开始一直以为是有一个规律的。
按照结束的顺序从小往大排列,如果相同取花费时间最小的。
一直wa。wa到绝望。真没想到是状态压缩。。。
枚举每种状态,注意逆序输出的方法。
这题真是不错。
DP枚举每种状态的同时,最小化他要补的时间。
还要记录他的前面那个,用来输出用。
还要记录当前天数。。下一个递推要用。
还有一个重要的地方就是存的是之前的状态
而不是值。用值无法创建一个连续的地方

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
const int maxn=200;
struct Node
{   string s;
     int first;//截止时间
     int second;//要开始的时间

}node[maxn];
struct DP
{   int cost;//最小花费
    int pre;//上一个数的状态
    int date;//当前天数

}dp[1<<20];
void output(int n)
{   if(n==0)return;
    int sta=n^dp[n].pre;
     sta>>=1;
     int pos=0;
     while(sta)
     {  sta>>=1;
         pos++;
     }
     output(dp[n].pre);
      cout<<node[pos].s<<endl;
}
int main()
{  int m;
   int t;
    scanf("%d",&t);
    while(t--)
    {   cin>>m;
       memset(dp,0,sizeof(dp));
       for(int i=0;i<m;i++)
       {   cin>>node[i].s;
           cin>>node[i].first;
           cin>>node[i].second;
       }
     int all=(1<<m)-1;
     bool vis[(1<<m)];
     memset(vis,false,sizeof(vis));
     vis[0]=true;
     for(int i=0;i<all;i++)
     {   for(int j=0;j<m;j++)
          {    if(!(i&(1<<j)))
              {   int dat=dp[i].date+node[j].second;//干完这个工作,干到哪了
                 int cos=dat-node[j].first;//要增加的时间
                 if(cos<0) cos=0;

                 int status=i|(1<<j);
                 dp[status].date=dat;
                  cos+=dp[i].cost;
                 if(!vis[status])
                 {   vis[status]=true;
                    dp[status].cost=cos;
                    dp[status].pre=i;
                 }
                  if(vis[status]&&dp[status].cost>cos)
                  {  dp[status].cost=cos;
                     dp[status].pre=i;
                  }
              }
          }
     }
 cout<<dp[all].cost<<endl;
    output(all);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值