Gym - 102219E : Optimal Slots(01背包)

http://codeforces.com/gym/102219/problem/E

The main hall of your residency is open for use by the local community and public. Since it was built on public donations, there is no charge of using it. Every weekend particularly on public holidays there are up to 50 reservations to use it for multiple events with different durations.You have been assigned by the residents to develop a program in choosing events to get most out of allocation time per weekend and have as short unused time as possible. Program should find the event(s) which fill(s) the allocation time best and print it in the same sequence as appears in the reservation list.

Input

Each test case consist of a single line.The line starts with two integer Tand N which is the time allocated for the hall to be used in the particular weekend and the number of events. The next T integer are the durations of the events (as appear in the reservation list). For example from the first line in sample data: T=5 hours, N, number of events =5, first event lasts for 1 hour, second is 2 hours, third is 3 hours, fourth is 4 hours, and the last one is 5 hours.

The input process will be terminated by a line containing 0.

Output

For each line of input value, in a single line, first, output a list of integers which are the selected events duration and another integer which is the sum of the selected events duration.

If there are multiple possible list of events, events that appear earlier in the list takes priority.

Example

Input

5 5 1 2 3 4 5
10 9 11 9 3 5 8 4 9 3 2
16 8 12 6 11 11 13 1 10 7
13 5 10 12 2 13 10
28 14 18 19 26 15 18 24 7 21 14 25 2 12 9 6
0

Output

1 4 5
3 5 2 10
6 10 16
13 13
19 7 2 28

题意分析:

给出总时间 t ,和n项活动的时间,怎么分配可以使用最多的不超过 t 的时间,按给出的顺序输出每个活动的时间。

解题思路:

01背包很好想,关键是如何记录路径,book[i][j]表示总时间为j时第 i 个活动是否选,dp[i][j]表示时间为 j 选到第 i 个活动时最多可以分配的时间,在更新dp[i][j]的时候同样可以更新book[i][j]。

在最后输出的时候判断book[i][t],即时间为 t 时, 第 i 个活动是否选中, 如果选中,更新t的值,继续判断。

#include <stdio.h>
#include <string.h>
#define N 55
int dp[N][N], a[N];
bool book[N][N];
int main()
{
	int n, t, i, j;
	while(scanf("%d", &t), t!=0)
	{
		scanf("%d", &n);
		for(i=n; i>=1; i--)
			scanf("%d", &a[i]);
		
		memset(dp, 0, sizeof(dp));
		memset(book, false, sizeof(book));
		for(i=1; i<=n; i++)
		{
			for(j=t; j>=a[i]; j--)
			{
				if(dp[i-1][j]>dp[i-1][j-a[i]]+a[i])
				{
					dp[i][j]=dp[i-1][j];
				} 
				else
				{
					dp[i][j]=dp[i-1][j-a[i]]+a[i];
					book[i][j]=true;
				}
			}
			for(j=a[i]-1; j>=0; j--)
				dp[i][j]=dp[i-1][j];
		}
		int t1=t;
		for(i=n; i>=1; i--)
			if(book[i][t]==true)
			{
				printf("%d ", a[i]);
				t-=a[i];
			}
		printf("%d\n", dp[n][t1]);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张宜强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值