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

来源:互联网 发布:win7如何安装linux系统 编辑:程序博客网 时间:2024/06/06 23:03
Washing Clothes

Description

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

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

Input

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

Output

For each test case output on a separate line the time the coupleneeds 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)
   returni;
 }
 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]);

  charch[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
原创粉丝点击