UVA 10163 Storage Keepers

  方法一、d[i][j][k]表示前i个人看j个货总保险值为k时的最小花费。时间复杂度较高。

//10163 	Storage Keepers 	Accepted 	C++ 	0.236 	2012-12-14 03:23:11
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 100+5, MAXM = 30+5, MAXP = 1000+5;
const int INF = 0x3f3f3f3f;
int N, M, P[MAXM];
int d[MAXM][MAXN][MAXP];
int main()
{
	while (scanf("%d%d", &N, &M))
	{
		if (!N && !M)
			break;
		for (int i = 1; i <= M; i++)
			scanf("%d", &P[i]);
		for (int i = 0; i <= M; i++)
			for (int j = 0; j <= N; j++)
				for (int k = 1; k <= 1000; k++)
					d[i][j][k] = INF;
		for (int i = 0; i < M; i++)
			for (int j = 0; j <= N; j++)
				for (int k = 0; k <= 1000; k++) if (d[i][j][k] < INF)
				{
					d[i+1][j][k] = min(d[i+1][j][k], d[i][j][k]);
					for (int l = 1; j+l <= N; l++)
					{
						if (j)
							d[i+1][j+l][min(k, P[i+1]/l)] = min(d[i+1][j+l][min(k, P[i+1]/l)], d[i][j][k]+P[i+1]);
						else
							d[i+1][j+l][P[i+1]/l]= min(d[i+1][j+l][P[i+1]/l], d[i][j][k]+P[i+1]);
					}
				}
		for (int k = 1000; k >= 0; k--)
			if (d[M][N][k] < INF)
			{
				printf("%d %d\n", k, d[M][N][k]);
				break;
			}
	}
	return 0;
}

  方法二、d[i][j]表示前i个人看j个货时最大的总保险值,f[i][j]表示前i个人看j个货并达到最大的总保险值时的最小花费。

//10163 	Storage Keepers 	Accepted 	C++ 	0.012 	2012-12-14 03:21:21
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 100+5, MAXM = 30+5, MAXP = 1000+5;
const int INF = 0x3f3f3f3f;
int N, M, P[MAXM];
int d[MAXM][MAXN], f[MAXM][MAXN];
int main()
{
	for (int i = 0; i <= 30; i++)
		d[i][0] = INF;
	while (scanf("%d%d", &N, &M))
	{
		if (!N && !M)
			break;
		for (int i = 1; i <= M; i++)
			scanf("%d", &P[i]);
		for (int i = 1; i <= M; i++)
			for (int j = 1; j <= N; j++)
			{
				d[i][j] = d[i-1][j];
				for (int k = 1; k <= j; k++)
					d[i][j] = max(d[i][j], min(d[i-1][j-k], P[i]/k));
			}
		for (int i = 0; i <= M; i++)
			for (int j = 1; j <= N; j++)
				f[i][j] = INF;
		for (int i = 1; i <= M; i++)
			for (int j = 1; j <= N; j++)
			{
				f[i][j] = f[i-1][j];
				for (int k = 1; k <= j; k++)
					if (P[i]/k >= d[M][N])
						f[i][j] = min(f[i][j], f[i-1][j-k]+P[i]);
			}
		printf("%d %d\n", d[M][N], d[M][N] ? f[M][N] : 0);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值