POJ 3211 Washing Clothes (分组背包+0/1背包)

来源:互联网 发布:5年内诞生超人工智能 编辑:程序博客网 时间:2024/05/17 03:59

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 4red blue yellow2 red3 blue4 blue6 red0 0
Sample Output
10

 【题解】

 大致题意:有一堆衣服要洗,每件衣服对应一个洗衣时间,只有两个人,而且这些衣服还分为好几种颜色,现在两个人只能同时洗同一种颜色的衣服,问最少多久可以洗完。

  

 分析:

  两人每次只能洗同一种颜色的衣服,那就意味着其他颜色的衣服对当前状态没有影响,所以可以用分组背包思想,然后再考虑,每种颜色的衣服都有一个洗衣时间,而总的时间要最少,可以想象,用时最少的情况莫过于对于同一种颜色的衣服,两个人各自用去总时间的一半,就为最短时间,所以这个一半时间就相当于0/1背包问题中的背包容量,然后每件衣服所需的时间就是物品价值,这样,求出一半时间内一个人洗衣服用时的最大时间max_t,则洗这种颜色的衣服用的最短时间就是总时间减去这个最大时间max_t,因为max_t总是小于等于最大时间的一半的。

 这样每次求出一种颜色衣服所需的最小时间,加起来就是总的最小时间。


【AC代码】

 

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;const int N=1005;int dp[100000];int m,n;struct clothes{    string colors;//每种衣服的颜色    int sum; //每种衣服要洗完所用的总时间    int num; //每种衣服的数量    int times[1000]; //每种衣服第i件需要的洗衣时间}clo[12];int main(){    string s;    int a;    while(cin>>m>>n)    {        if(!(m+n)) break;        for(int i=1;i<=m;++i)        {            cin>>clo[i].colors;            clo[i].sum=clo[i].num=0; //记得清零        }        for(int i=1;i<=n;++i)        {            cin>>a>>s;            for(int j=1;j<=m;++j)            {                if(s==clo[j].colors)                 {                    int cnt=clo[j].num;                    clo[j].times[cnt]=a;                    clo[j].sum+=a;                    clo[j].num++;                }            }        }        int ans=0;        for(int i=1;i<=m;++i)//分组背包        {            memset(dp,0,sizeof(dp));            int half_time=clo[i].sum/2;            for(int j=0;j<clo[i].num;++j) //多重背包            {                for(int k=half_time;k>=clo[i].times[j];--k)                {                    dp[k]=max(dp[k],dp[k-clo[i].times[j]]+clo[i].times[j]);                }            }            ans+=clo[i].sum-dp[half_time]; //总洗衣时间减去一个人洗衣用的最大时间        }        cout<<ans<<endl;    }    return 0;}