ACM: 动态规划题 poj 3211 背包变…

Washing Clothes

Description

Dearboy was so busy recently that now he has piles of clothes to wash. Luckily, he has a beautiful and hard-working girlfriend to help him. The clothes are in varieties of colors but each piece of them can be seen as of only one color. In order to prevent the clothes from getting dyed in mixed colors, Dearboy and his girlfriend have to finish washing all clothes of one color before going on to those of another color.

From experience Dearboy knows how long each piece of clothes takes one person to wash. Each piece will be washed by either Dearboy or his girlfriend but not both of them. The couple can wash two pieces simultaneously. What is the shortest possible time they need to finish the job?

Input

The input contains several test cases. Each test case begins with a line of two positive integers M and N (M < 10, N < 100), which are the numbers of colors and of clothes. The next line contains M strings which are not longer than 10 characters and do not contain spaces, which the names of the colors. Then follow N lines describing the clothes. Each of these lines contains the time to wash some piece of the clothes (less than 1,000) and its color. Two zeroes follow the last test case.

Output

For each test case output on a separate line the time the couple needs for washing.

Sample Input

3 4
red blue yellow
2 red
3 blue
4 blue
6 red
0 0

Sample Output

10

 

题意: 一对情侣洗衣服, 现在有m种颜色的衣服n件, 为了不让混着洗衣服染色了, 所以洗完

      一种颜色的衣服再洗另外的一种. 现在分配给2个人洗, 求出最小的洗完全部时间.

 

解题思路:

      1. 每一种衣服都是独立, 因此我们分别求出每一种衣服洗完需要的最小时间, 累加起来即可.

      2. 每一种衣服时间总和是sum[i], 现在要分配给2个人洗, 怎么样才是最小时间. 即是2个人

         的洗衣服时间尽可能接近sum[i]/2; 因此, sum[i]/2成为了一个临界值.

         问题分析:

         (1). 考虑其中一个人, 现在num[i]表示i类衣服的数量, 每件衣服有2中分配结果, 要么

              分配给这个人洗, 要么不分配给这个人洗. 明显的0-1背包问题.

         (2). 上述的临界值可以看成是背包的容量(时间容量), 每件衣服分配0-1状态. 因此,可

              以用背包问题求解. 方程: dp[j] = max(dp[j], dp[j-time[i][k]]+time[i][k]);

         (3). 当然这样就是求出其中一个人的需要时间, 但是实际上一类衣服洗完的时间是2个人

              中时间较大的那一个决定. 因此, 结果: sum[i]-dp[ sum[i]/2 ];

 

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 1005
#define MAXSIZE 105

int n, m;
char str[MAXSIZE][12];
int num[MAXSIZE], sum[MAXSIZE], cost[MAX][MAXSIZE];
int dp[MAX*MAXSIZE];

inline int max(int a, int b)
{
 return a > b ? a : b;
}

inline int find(char *ch)
{
 for(int i = 1; i <= m; ++i)
 {
  if( strcmp(str[i], ch) == 0 )
   return i;
 }
 return -1;
}

int DP(int index, int v)
{
 memset(dp, 0, sizeof(dp));
 for(int i = 1; i <= num[index]; ++i)
 {
  for(int j = v; j >= cost[index][i]; --j)
  {
   dp[j] = max( dp[j], dp[ j-cost[index][i] ]+cost[index][i] );
  }
 }
 return sum[index]-dp[v];
}

int main()
{
 int i;
// freopen("input.txt", "r", stdin);
 while(scanf("%d %d", &m, &n) != EOF)
 {
  if(n == 0 && m == 0) break;
  memset(num, 0, sizeof(num));
  memset(sum, 0, sizeof(sum));
  memset(cost, 0, sizeof(cost));
  for(i = 1; i <= m; ++i)
   scanf("%s",str[i]);

  char ch[12];
  int temp;
  for(i = 1; i <= n; ++i)
  {
   scanf("%d %s",&temp, ch);
   int index = find(ch);
   sum[ index ] += temp;
   num[ index ]++;
   cost[ index ][ num[index] ] = temp;
  }

  int result = 0;
  for(i = 1; i <= m; ++i)
   result += DP(i, sum[i]/2);

  printf("%d\n", result);
 }
 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值