hdu3182 状态压缩dp

题意:
      一个人做汉堡包,每个汉堡包有自己的花费和价值,某些汉堡包必须是在其他的某些汉堡包已经做好了的前提下才能制作,给你这个人的初始钱数,问最大的价值是多少。

思路:

      比较简单的一个题目,首先我们开一个数组dp[i]表示i状态(状态压缩)时的最大价值,把每一个状态都用这n个汉堡包更新一下,还的开个数组money[i]表示的是i状态是的剩余钱数,更新的时候记住一点就是每个点只能用一次,也就是当前状态里如果有i这个点,那么i不能在来更新了。


#include<stdio.h>
#include<string.h>

int dp[1<<16];
int cost[20] ,vie[20];
int money[1<<16];
int limit[20][20];

int maxx(int x ,int y)
{
   return x > y ? x : y;
}

bool ok(int ii ,int now)
{
   for(int i = 1 ;i <= limit[ii][0] ;i ++)
   if(!(now & (1 << (limit[ii][i] - 1)))) return 0;
   return 1;
}

int main ()
{
   int t ,n ,m ,i ,j;
   scanf("%d" ,&t);
   while(t--)
   {
      scanf("%d %d" ,&n ,&m);
      for(i = 1 ;i <= n ; i++)
      scanf("%d" ,&vie[i]);
      for(i = 1 ;i <= n ;i ++)
      scanf("%d" ,&cost[i]);
      for(i = 1 ;i <= n ;i ++)
      {
         scanf("%d" ,&limit[i][0]);
         for(j = 1 ;j <= limit[i][0] ;j ++)
         scanf("%d" ,&limit[i][j]);
      }
      
      for(i = 0 ;i <= (1 << n) - 1 ;i ++)
      dp[i] = -1000000000 ,money[i] = 0;
      dp[0] = 0 ,money[0] = m;
      int Ans = 0;
      for(i = 0 ;i <= (1<<n) - 1 ;i ++)
      for(j = 1 ;j <= n ;j ++)
      {
         if(i & (1 << (j - 1))) continue;
         int now = i|(1<<(j-1));
         if(dp[now] < dp[i] + vie[j] && money[i] >= cost[j] && ok(j ,i))
         {
            dp[now] = dp[i] + vie[j];
            Ans = maxx(dp[now] ,Ans);
            money[now] = money[i] - cost[j];
         }
      }
      printf("%d
" ,Ans);
   }
   return 0;
}
            

原文地址:https://www.cnblogs.com/csnd/p/12062738.html