题意:两个人洗衣服, 每种颜色的衣服有多件, 要求两人只能同时洗相同颜色的衣服, 求洗衣服的最短时间。
分析:因为只能同时洗相同颜色的衣服, 因此可将不同颜色的衣服看为不同的组, 分别求出来每组的最短时间, 其和即为所求;每组最短时间就是0 1背包;对于每种颜色洗它都有一个总时间,要求洗这种颜色的最少时间,就是求看能不能一个人洗这种颜色的衣服达到总时间的一半,也就是让两个人洗这种颜色的衣服的时间尽可能相同。
解题思路:先求出洗每种颜色的衣服所用的总时间,为了让两个人所用时间尽可能相同,把总时间的一半当做背包容量,每件衣服所花费的时间既是物体体积,又是物品价值,这样就转化为01背包,求背包的最大价值,然后用这种颜色的总时间减去最大价值就是洗这种颜色的衣服所用的最短时间。
注意:dp数组要用滚动数组,不然会超时.
使用vector版本:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<map>
using namespace std;
int dp[2][100005];
int main()
{
map<string, int> mp;
vector<int> clo[11];
int m, n, cnt, time, sum[11], ans, an;
string tem;
while(cin >> m >> n)
{
if(m == 0 && n == 0)
break;
mp.clear();
for(int i = 0; i <= 10; i++)
clo[i].clear();
memset(sum, 0, sizeof(sum));
ans = cnt = 0;
for(int i = 0; i < m; i++)
{
cin >> tem;
mp[tem] = ++cnt;
}
for(int i = 0; i < n; i++)
{
cin >> time >> tem;
clo[mp[tem]].push_back(time);
sum[mp[tem]] += time;
}
int fi;
for(int i = 1; i <= cnt; i++)
{
fi = 0;
memset(dp, 0, sizeof(dp));
int num = clo[i].size();
int wei = sum[i] / 2;
for(int j = 0; j < num; j++)
{
for(int k = 0; k <= wei; k++)
{
if(k < clo[i][j])
dp[!fi][k] = dp[fi][k];
else
dp[!fi][k] = max(dp[fi][k], dp[fi][k-clo[i][j]] + clo[i][j]);
}
fi = !fi;
}
//an = max(sum[i] - dp[fi][wei], dp[fi][wei]);
an = sum[i] - dp[fi][wei];
ans += an;
}
cout << ans << endl;
}
return 0;
}
不使用vector版本:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<map>
using namespace std;
int dp[2][100005], clo[11][100];
int main()
{
map<string, int> mp;
int m, n, cnt, time, sum[11], ans, an, tol[11];
string tem;
while(cin >> m >> n)
{
if(m == 0 && n == 0)
break;
mp.clear();
memset(sum, 0, sizeof(sum));
memset(tol, 0, sizeof(tol));
ans = cnt = 0;
for(int i = 0; i < m; i++)
{
cin >> tem;
mp[tem] = ++cnt;
}
for(int i = 0; i < n; i++)
{
cin >> time >> tem;
clo[mp[tem]][tol[mp[tem]]++] = time;
sum[mp[tem]] += time;
}
int fi;
for(int i = 1; i <= cnt; i++)
{
fi = 0;
memset(dp, 0, sizeof(dp));
int num = tol[i];
int wei = sum[i] / 2;
for(int j = 0; j < num; j++)
{
for(int k = 0; k <= wei; k++)
{
if(k < clo[i][j])
dp[!fi][k] = dp[fi][k];
else
dp[!fi][k] = max(dp[fi][k], dp[fi][k-clo[i][j]] + clo[i][j]);
}
fi = !fi;
}
an = max(sum[i] - dp[fi][wei], dp[fi][wei]);
ans += an;
}
cout << ans << endl;
}
return 0;
}