Poj 3211 Washing Clothes (DP_背包)

题目链接:http://poj.org/problem?id=3211


题目大意:出题者无比嚣张地show幸福。他们夫妻两洗衣服,衣服有m种颜色,每种颜色又有若干件,每件衣服洗完需要特定的时间,要求每种颜色放在一起洗,洗完才能洗其他衣服。最后问洗完需要的最少时间。


解题思路:由于每种颜色必须分开洗,那我们可以把同一种颜色的分到一个组内,这样分开计算时间再累加起来。那么每组花费的最少时间怎么算呢?如果总和sum,每个人洗sum/2的时间肯定最理想,否则一方少于sum/2,一方多于sum/2,这组的时间久是sum/2,那我们只要找到最接近sum/2的组合结果tpsum,然后与sum-tpsum比较取大者。差不多就是这样,拿生活的事来模拟最有意思了。

    状态转移方程:if (dp[k-cost[i][j]]) dp[k] = 1; (i为第i组,j为第i组第j个,k为容量) ,复杂度O(V*sum(num[i]))


测试数据:

3 4
red blue yellow
2 red
3 blue
4 blue
6 red

3 4
red blue yellow
3 red
3 red
4 blue
4 blue


代码:

#include <stdio.h>
#include <string.h>
#include <map>
#include <string>
using namespace std;
#define MIN 500
#define MAX 110000
#define max(a,b) (a)>(b)?(a):(b)


char name[MIN][MIN];
map<string,int> mmap;
int m,tot,num[MIN],sum[MIN];
int ans,n,cost[MIN][110],dp[MAX];


int main()
{
	int i,j,k,tpk;
	char tpstr[MIN];
		
	while (scanf("%d%d",&m,&n), n + m) {

		mmap.clear();
		ans = tot = 0;
		memset(num,0,sizeof(num));
		memset(sum,0,sizeof(sum));
		for (i = 1; i <= m; ++i) {

			scanf("%s",name[i]);
			mmap[string(name[i])] = ++tot;
		}
		for (i = 1; i <= n; ++i) {

			scanf("%d%s",&tpk,tpstr);
			k = mmap[string(tpstr)];
			sum[k] += tpk;
			cost[k][++num[k]] = tpk; 
		}


		for (i = 1; i <= tot; ++i) {

			memset(dp,0,sizeof(dp));
			tpk =  sum[i] / 2;
			for (dp[0] = j = 1; j <= num[i]; ++j)
				for (k = tpk; k >= cost[i][j]; --k)
					if (dp[k-cost[i][j]]) dp[k] = 1;
			while (!dp[tpk]) tpk--;
			ans += max(tpk,sum[i]-tpk);
		}
		printf("%d\n",ans);
	}
}

本文ZeroClock原创,但可以转载,因为我们是兄弟。

你可能感兴趣的:(生活,String,测试)