pku 1170 Shopping Offers dp+状态压缩

//挺好的题目 蛮经典的

#include <iostream>
using namespace std;

const int MAXN = 6*6*6*6*6;
int dp[MAXN];
int product[5][3];
int hash[1000];
int offer_price[105];
int offer[105][5];

int getNum(int a[5])
{
 int num = 0, i;
 for (i = 0; i < 5; ++i)
 {
  num = num*6 + a[i];
 }
 return num;
}

void setNum(int num, int a[5])
{
 int i = 4;
 while (num)
 {
  a[i--] = num % 6;
  num = num / 6;
 }
 for (; i >= 0; --i)
 {
  a[i] = 0;
 }
}

bool IsCan(int a[5], int b[5])
{
 int i;
 for (i = 0; i < 5; ++i)
 {
  if (a[i] < b[i])
  {
   break;
  }
 }
 return i == 5;
}
int main()
{
 int b, s;
 while (scanf("%d", &b) != EOF)
 {
  int i, j, k;
  memset(product, 0, sizeof(product));
  memset(offer, 0, sizeof(offer));
  for (i = 0; i < MAXN; ++i)
  {
   dp[i] = 0XFFFFFFF;
  }
  
  for (i = 0; i < b; ++i)
  {
   scanf("%d %d %d", &product[i][0], &product[i][1], &product[i][2]);
   hash[product[i][0]] = i;
  }
  scanf("%d", &s);
  for (i = 0; i < s; ++i)
  {
   int n;
   scanf("%d", &n);
   for (j = 0; j < n; ++j)
   {
    int c, num;
    scanf("%d %d", &c, &num);
    offer[i][hash[c]] = num;
   }
   scanf("%d", &offer_price[i]);
  }

  for (; i < b+s; ++i)
  {
   offer[i][i-s] = 1;
   offer_price[i] = product[i-s][2];
  }

  int temp[5];
  for (i = 0; i < 5; ++i)
  {
   temp[i] = product[i][1];
  }
  int result = getNum(temp);
  dp[result] = 0;
  for (i = result; i >= 0; --i)
  {
   setNum(i, temp);
   for (k = 0; k < b+s; ++k)
   {
    if (IsCan(temp,offer[k]))
    {
     int newTemp[5], newFlag;
     for (j = 0; j < 5; ++j)
     {
      newTemp[j] = temp[j] - offer[k][j];
     }
     newFlag = getNum(newTemp);
     if (dp[i] + offer_price[k] < dp[newFlag])
     {
      dp[newFlag] = dp[i] + offer_price[k];
     }
    }
   }
  }
  printf("%d\n", dp[0]);
 }
 return 0;
}

posted on 2009-07-20 22:01  ZAFU_VA  阅读(341)  评论(0)    收藏  举报

导航