Posted on 2010-08-03 22:23
Onway 阅读(237)
评论(0) 编辑 收藏 引用 所属分类:
伤不起的ACM
前几天刚学0-1背包的时候就看过了这题,但没什么思路,今天算是学过了三种背包了,再看回这题,还是没什么思路。怎么人家都说是0-1背包呢,想了很久还是不知道怎么背包法,笨死。无奈看了discuss,豁然开朗。原来背包还可以这样玩,太有意思了。
题意:
有一堆衣服,多种颜色,每种颜色的可能有多件。有两个洗衣服速度相同的人要洗干净这堆衣服。每件衣服都有一个洗干净所要花费的时间。两个人同时工作,但只有一种颜色的衣服都洗完后,两人才可以开始洗其他颜色。问这两个人洗完这堆衣服最少需要多少时间。
思路:将某种颜色的时间之和的一半作为0-1背包的容量,物品的价值与重量等同于该种颜色的衣服所花费的时间,这是关键思路啊!只要求得这个背包的能获得的最大价值,就是说在这一半的时间里,有多少是被最有效利用的。然后总时间减去这个有效利用的,就是洗完这堆衣服最少要花费的时间。
要处理这个题的输入可能比较麻烦。将输入的数据转化为要进行背包的数据后,背包部分就简单了。
如果,这个题改一下,要分两行输出没人要洗的衣服呢?又怎么处理了?
1
#include <iostream>
2
#include <string>
3
#include <algorithm>
4
using namespace std;
5
const int MAX=50000; //变成两个背包以后,一个的容量最多就是50000
6
char name[150]; //这个没什么用,就是吃掉那一行的名字输入
7
int sum[10]; //每一种颜色的时间之和
8
struct clother
9

{
10
int tim;
11
string color;
12
}clo[100];
13
int data[12][100]; //将原来读入的数据转化后好进行0-1背包
14
int dp[10][MAX+1]; //不解析
15
bool cmp(clother a,clother b)
16

{return a.color<b.color;}
17
18
int main()
19

{
20
int m,n;
21
while(cin>>m>>n&&(n||m))
22
{
23
getchar();
24
cin.getline(name,150);
25
int i,j,k;
26
for(i=1;i<=n;++i)
27
cin>>clo[i].tim>>clo[i].color;
28
sort(clo+1,clo+1+n,cmp); //输入完以后马上排序
29
30
data[1][1]=clo[1].tim;
31
for(i=2,j=1,k=2;i<=n;++i) //data[j][0]是记录第j种颜色的衣服件数
32
if(clo[i].color==clo[i-1].color)
33
data[j][k++]=clo[i].tim;
34
else
35
{
36
data[j][0]=--k;
37
++j;
38
k=2;
39
data[j][1]=clo[i].tim;
40
}
41
data[j][0]=--k;
42
n=j; //n变成了需要进行背包的颜色种数
43
//这一段很容易理解,但可能处理比较麻烦,从排序后的第二个数据,即i=2开始
44
//感觉这样比较好处理
45
46
memset(sum,0,sizeof(sum)); //这段是数据转化后进行时间之和统计
47
for(i=1;i<=n;++i)
48
{
49
for(j=1;j<=data[i][0];++j)
50
sum[i]+=data[i][j];
51
}
52
53
memset(dp,0,sizeof(dp)); //这一段就是进行0-1背包了
54
for(i=1;i<=n;++i)
55
for(j=1;j<=data[i][0];++j)
56
for(k=MAX;k>=data[i][j];--k)
57
dp[i][k]=dp[i][k]>dp[i][k-data[i][j]]+data[i][j]?
58
dp[i][k]:dp[i][k-data[i][j]]+data[i][j];
59
60
for(i=1;i<=n;++i)
61
sum[i]-=dp[i][sum[i]/2];
62
//摘自poj discuss TangMing 的一句话:
63
//把sum[i]/2的背包最大填满,第i种颜色耗时就为 sum[i]-dp[sum[i]/2];
64
//虽然这段代码很短,但是整个思路的关键
65
66
for(i=1;i<=n;++i)
67
sum[0]+=sum[i];
68
cout<<sum[0]<<endl;
69
}
70
return 0;
71
}