http://poj.org/problem?id=3211
小两口洗衣服,只有一种颜色的衣服洗完才能洗下一种颜色,两人同时洗问需要的最小时间。
这里一种颜色的衣服所需的总时间可以求出,求出每种颜色衣服所需最小时间便求出了ans。每种颜色的衣服总时间有了,让求两个人最短完成时间,就相当于给你一个数让你分成两份,并让这两份尽可能的小,显然这个数的一半就是答案。在这里也就是两个人洗衣服的时间尽可能相同。
怎么让一个人洗衣服的时间尽可能等于总时间的一半呢?01背包,最大容量为sum[i]/2,尽可能将背包装满即可。ans += sum[i] - dp[sum[i]/2] ;,ans便为解。
代码:
#include<cstdio>
#include<cstring>
#define Max(a, b) a>b?a:b
using namespace std ;
int dp[100*1000+5] ;
int sum[10] ;
char color[10][10] ;
struct Clo{
char col[10] ;
int time ;
} clo[101];
int main(){
int n, m, i, j, t, ans ;
while(~scanf("%d%d", &n, &m)&&n+m){
memset(sum, 0, sizeof(sum)) ;
for(i=0; i<n; i++)
scanf("%s", color[i]) ;
for(i=0; i<m; i++){
scanf("%d%s", &clo[i].time, clo[i].col) ;
for(j=0; j<n; j++){
if(!strcmp(color[j], clo[i].col)){
sum[j] += clo[i].time ;//统计总时间
break ;
}
}
}
ans = 0 ;
for(i=0; i<n; i++){
for(j=0; j<=sum[i]/2; j++)
dp[j] = 0 ;
for(j=0; j<m; j++){
if(!strcmp(clo[j].col, color[i]))
for(int v=sum[i]/2; v>=clo[j].time; v--)
dp[v] = Max(dp[v], dp[v-clo[j].time]+clo[j].time) ;
ans += sum[i] - dp[sum[i]/2] ;
}
printf("%d\n", ans) ;
}
return 0 ;
#include<cstring>
#define Max(a, b) a>b?a:b
using namespace std ;
int dp[100*1000+5] ;
int sum[10] ;
char color[10][10] ;
struct Clo{
char col[10] ;
int time ;
} clo[101];
int main(){
int n, m, i, j, t, ans ;
while(~scanf("%d%d", &n, &m)&&n+m){
memset(sum, 0, sizeof(sum)) ;
for(i=0; i<n; i++)
scanf("%s", color[i]) ;
for(i=0; i<m; i++){
scanf("%d%s", &clo[i].time, clo[i].col) ;
for(j=0; j<n; j++){
if(!strcmp(color[j], clo[i].col)){
sum[j] += clo[i].time ;//统计总时间
break ;
}
}
}
ans = 0 ;
for(i=0; i<n; i++){
for(j=0; j<=sum[i]/2; j++)
dp[j] = 0 ;
for(j=0; j<m; j++){
if(!strcmp(clo[j].col, color[i]))
for(int v=sum[i]/2; v>=clo[j].time; v--)
dp[v] = Max(dp[v], dp[v-clo[j].time]+clo[j].time) ;
ans += sum[i] - dp[sum[i]/2] ;
}
printf("%d\n", ans) ;
}
return 0 ;
}