简单的01背包。
题意:两口子洗衣服,他们不能同时洗一件衣服,但是能同时洗两件衣服。但只有一个盆,只能同一种颜色的衣服在一起洗,否者会搞成五颜六色的。洗每一件衣服都有时间,求最短的洗衣时间。
做法:
把每种颜色分开讨论。
对于每一种颜色:
每件衣服是一个物品,最多只能取一次。cost为洗衣服的时间,weight为洗衣服的时间。
背包容量为一个人需要洗衣服的总时间。
因为是两个人在洗衣服,那这两个人中洗衣服的时间最长的就是两个人一起洗衣服所用的时间。
当洗了一半或者一半以上的耗时的时候,即为两个人一起洗衣服的耗时。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<stdlib.h>
#define INT_MAX 0x7fffffff
#define INF 999999
#define max3(a,b,c) (max(a,b)>c?max(a,b):c)
#define min3(a,b,c) (min(a,b)<c?min(a,b):c)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
struct node
{
int u;
int v;
int w;
bool friend operator < (node a, node b){
return a.w < b.w;
}
}edge[1001];
int gcd(int n,int m){if(n<m) swap(n,m);return n%m==0?m:gcd(m,n%m);}
int lcm(int n,int m){if(n<m) swap(n,m);return n/gcd(n,m)*m;}
int dp[100001];
int main()
{
char str[101][101];
int num[101][101];
int sum[101];
int i,j,k;
int n,m;
while(scanf("%d %d%*c",&m,&n)&&(m||n))
{
for(i=0;i<m;i++)
{
scanf("%s",str[i]);
}
mem(sum,0);
mem(num,0);
int t;
char color[1001];
for(i=0;i<n;i++)
{
scanf("%d %s%*c",&t,color);
for(j=0;j<m;j++)
{
if(strcmp(color,str[j])==0)
{
num[j][sum[j]++]=t;break;
}
}
}
int ans=0;
for(i=0;i<m;i++)
{
int ss;
ss=0;
int su;
su=sum[i];
for(j=0;j<su;j++)
{
ss+=num[i][j];
}
int ll;
ll=ss;
mem(dp,-1);
dp[0]=0;
for(j=0;j<su;j++)
{
for(k=ss;k>=num[i][j];k--)
{
if(dp[k-num[i][j]]!=-1)
{
dp[k]=max(dp[k],dp[k-num[i][j]]+num[i][j]);
if(dp[k]>=((ss+1)/2)&&ll>k)
{
ll=k;
}
}
}
}
ans+=ll;
}
printf("%d\n",ans);
}
return 0;
}