#include<iostream>
#include<fstream>
using namespace std;
struct clrg
{
char color[16];
int sum;
int i;
int a[100];
};
static int dp[100001];
//#define DEBUG
int main()
{
#ifdef DEBUG
fstream cin("G:\\book\\algorithms\\acm\\Debug\\dat.txt");
#endif
int m, n;
struct clrg group[10];
while (cin >> m >> n)
{
if (m == 0 && n == 0) return 0;
int i, j, w;
char color[16];
int result = 0;
memset(group, 0, sizeof group);
for (i = 0; i < m; i++)
cin >> group[i].color;
for (i = 0; i < n; i++)
{
cin >> w >> color;
for (j = 0; j < m; j++)
if (!strcmp(group[j].color, color))
{
group[j].sum += w; group[j].a[group[j].i++] = w;
break;
}
}
for (i = 0; i < m; i++)
{
int num = group[i].i;
int vol = group[i].sum / 2;
int k;
memset(dp, 0 , sizeof dp);
for (j = 0; j < num; j++)
{
int b = group[i].a[j];
for (k = vol; k >= b; k--)
{
if (dp[k] < dp[k - b] + b)
dp[k] = dp[k - b] + b;
}
}
result += group[i].sum - dp[vol];
}
cout << result << "\n";
}
return 0;
}
按照颜色对衣服进行分类,对每类的处理方法是相同的。将一组数据分成两组使得两组和的差最小。
所以该题实质上是数据a[.....]划分成为2个部分,两部分的和的差最小。
解法: 使用一次背包。简单一次背包的解法不再赘述。
背包大小vol = sum(a) / 2; dp[vol] 就是偏小的部分的总大小。