链接:
http://poj.org/problem?id=3211
题目大意:
Dearboy和他的女朋友一起洗m件衣服,共有n总颜色(每件衣服只有一种颜色)。 为了放置不同颜色互染,每次只能洗一种颜色的衣服,在这件衣服洗完之前不能洗另外一种衣服。 Dearboy和他女朋友可以同时一起洗衣服,但是不能同时洗同一件衣服,也不能同时洗不同种颜色的衣服。
一只每件衣服所需时间,问最少花费多少时间可以全部洗完。
分析:
首先可以很直观的判定,一定是把一种颜色的所有衣服都洗完再接着洗另外一种颜色的衣服,洗每种颜色所有衣服的总时间是分开独立的。
关键是洗同一种颜色的衣服时,Dearboy和他的女朋友怎样分配任务才可以最快完成? 最理想的情况时,两人各洗一半的时间。 所以,我们要尽量分配给两人的任务时长接近总时长的一半,最后洗完单种颜色的衣服所花的时间,取决于时长较大的那个。
很明显的可以用01背包来做,每件衣服的时间是容量也是价值,总时间的一半为背包的容量,然后01背包。
代码:
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<string>
#define MP make_pair
#define SQ(x) ((x)*(x))
using namespace std;
typedef long long int64;
const int MAXN = 110;
const int INF = 0x3f3f3f3f;
int n, m;
int h[25];
int w[12][MAXN], sum[12], num[12];
int f[MAXN*1000];
int main(){
char color[12];
int t;
while(~scanf("%d%d", &n, &m) && n+m){
map<string, int>mp;
for(int i=0; i<n; ++i){
scanf("%s",color);
mp[color] = i;
}
for(int i=0; i<=n; ++i)
sum[i] = num[i] = 0;
for(int i=0; i<m; ++i){
scanf("%d%s", &t, color);
int pt=mp[color];
w[pt][num[pt]++] = t;
sum[pt] += t;
}
int ans = 0;
for(int k=0; k<n; ++k){
for(int i=0; i<=sum[k]/2; ++i) f[i] = 0;
for(int i=0; i<num[k]; ++i){
for(int v=(sum[k]>>1); v>=w[k][i]; --v)
f[v] = max(f[v], f[v-w[k][i]]+w[k][i]);
}
ans += sum[k]-f[sum[k]>>1];
}
printf("%d\n",ans);
}
return 0;
}