背包)"/>
POJ 3211 Washing Clothes(01背包)
POJ 3211 Washing Clothes(01背包)
=3211
题意:
有m (1~10)种不同颜色的衣服总共n (1~100)件,Dearboy和她的girlfriend两个人要一起洗完全部衣服,为了预防色彩混合,他们每次只能同时洗同一种颜色的衣服,给出洗完每件衣服所需的时间time和它的颜色color,求出Dearboy和她的girlfriend最少用多少时间能洗完成全部衣服。
分析:
由于每种颜色的衣服是分开洗的, 所以我们可以把所有衣服按颜色分类, 然后每次看洗一种颜色的衣服最少需要花多少时间即可.
假设当前第i种颜色的衣服要洗, 由于有两个人, 我们明显让这两个人洗衣服的时间尽量平均才能使得该种衣服洗的时间尽量短.
那么这就是一个01背包问题了, 选择衣服使得一个人洗衣服的时间在<=sum/2的前提下尽量长.
对于同一种颜色的衣服有下面01背包过程:
令dp[i][j]=x表示只在前i件衣服里面选且总时间<=j时, 能达到的最大时间为x.
初始化: dp全为0.
状态转移: dp[i][j] = max( dp[i-1][j] , dp[i-1][j-time[i]]+time[i])
最终所求: 该种衣服所花时间== sum-dp[n][sum/2]. 其中sum为该种衣服所花时间总和.
最终我们把每种衣服花的时间累加起来即可得到ans.
AC代码:
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<iostream>
#include<string>
using namespace std;
const int maxn=100000+5;int n; //衣服件数
int m; //颜色种数
int dp[maxn];
int num[10+5]; //num[i]=x表第i类颜色衣服有x个
int val[10+5][100+5];//val[i][j]=x表第i类颜色的第j个衣服需要花x时间洗
map<string,int> mp; //颜色与编号的映射int main()
{while(scanf("%d%d",&m,&n)==2){if(n==0&&m==0) break;memset(num,0,sizeof(num));//读取输入,存入对应数组for(int i=1;i<=m;i++){string s;cin>>s;mp[s]=i;}for(int i=1;i<=n;i++){int x;string s;cin>>x>>s;int type=mp[s];val[type][++num[type]]=x;}//做最多m次01背包int ans=0;for(int k=1;k<=m;k++){//1次01背包int sum=0;memset(dp,0,sizeof(dp));for(int i=1;i<=num[k];i++)sum+= val[k][i];for(int i=1;i<=num[k];i++){for(int j=sum/2;j>=val[k][i];j--)dp[j] = max(dp[j], dp[j-val[k][i]]+val[k][i]);}//累计结果ans+= sum-dp[sum/2];}printf("%d\n",ans);}return 0;
}
更多推荐
POJ 3211 Washing Clothes(01背包)
发布评论