Uva 624 CD

You have a long drive by car ahead. You have a tape recorder, but unfortunatelyyour best music is on CDs. You need to have it on tapes so the problem to solveis: you have a tape N minutes long. How to choose tracks from CD to get most outof tape space and have as short unused space as possible.


Assumptions:

  • number of tracks on the CD. does not exceed 20
  • no track is longer than N minutes
  • tracks do not repeat
  • length of each track is expressed as an integer number
  • N is also integer

Program should find the set of tracks which fills the tape best and print itin the same sequence as the tracks are stored on the CD

 

Any number of lines. Each one contains value N, (after space) number of tracksand durations of the tracks. For example from first line in sample data: N=5,number of tracks=3, first track lasts for 1 minute, second one 3 minutes, nextone 4 minutes


Set of tracks (and durations) which are the correct solutions andstring `` sum:" and sum of duration times.


5 3 1 3 4
10 4 9 8 4 2
20 4 10 5 7 4
90 8 10 23 1 2 3 4 5 7
45 8 4 10 44 43 12 9 8 2


1 4 sum:5
8 2 sum:10
10 5 4 sum:19
10 23 1 2 3 4 5 7 sum:55
4 10 12 9 8 2 sum:45


本题属于01背包:需要注意的2点:1:此题中可视重量的等于价值。

2:输出比较麻烦。使用了DFS

对于220次方,差不多等于87次方,时间复杂度仍可以接受!!!

潜意识里总以为220次方很大。会超时。。。!!!  要改了这个潜意识!!!!

先用01背包的常规方法求出最大值,在用dfs搜索最大值时的数据并输出。

注意搜索顺序,使第一次搜索到的答案即为所求!!!



#include<stdio.h>
#include<string.h>

#define MAXN 21

int c[MAXN],temp[MAXN];
int f[100001];
int num,N,count,ok;

void dfs(int pos,int v)
{
	if(ok)
		return ;
	if(v==f[N])
	{
		int i;
		for(i=1;i<=count;i++)
		{
			printf("%d ",temp[i]);
		}
		ok=1;
		return ;
	}
	if(v>f[N] || pos == num)
		return ;
	temp[++count]=c[pos+1];
	dfs(pos+1,v+c[pos+1]);
	count--;
	dfs(pos+1,v);
}

int main(void)
{
//	freopen("d:\\in.txt","r",stdin);
	while(scanf("%d",&N)==1)
	{
		int i,j;
		scanf("%d",&num);
		for(i=1;i<=num;i++)
			scanf("%d",&c[i]);
		memset(f,0,sizeof(f));
		for(i=1;i<=num;i++)
			for(j=N;j>=c[i];j--)
			{
				if(f[j]<f[j-c[i]]+c[i])
				{
					f[j]=f[j-c[i]]+c[i];
				}
			}
		count=0;
		ok=0;
		dfs(0,0);
		printf("sum:%d\n",f[N]);
	}
	return 0;
}

ZeroClock:

解题思路由于要输出路径,不能再用滚动数组,要用二维数组,至少我没想到怎么用滚动数组实现。在转移的时候记录下path[i][j]

如果选择,那么它为1,否则为0.那么在递归输出路径的时候,就可以根据这个物品是否使用,然后j减去cost[i]就是上一个容量。

具体见代码,不影响O(V*N)的复杂度。

感觉零点的代码应该比我的快,但是提交了一次发现我的0.020s  而零点的0.558,把零点的代码在初始化上优化下 时间变为 0.316.

说明了零点的代码初始化上用了太多的时间了!!!

倒也是  数组比较大!!!!!


#include <stdio.h>
#include <string.h>
#define MAX 110000


int n,m,time[100],ans[100];
int maxx,path[30][MAX],dp[30][MAX];


int main()
{
	int i,j,k;


	while (scanf("%d",&m) != EOF) {

		scanf("%d",&n);
		for (i = 1; i <= n; ++i)
			scanf("%d",&time[i]);

			
		memset(dp,0,sizeof(dp));
		memset(path,0,sizeof(path));
		dp[0][0] = 1;
		for (i = 1; i <= n; ++i) {

			for (j = m; j >= time[i]; --j)
				if (dp[i-1][j-time[i]]) dp[i][j] = 1;
			for (j = 0; j <= m; ++j)
				if (dp[i][j] == 1) path[i][j] = 1;
				else if (dp[i-1][j]) dp[i][j] = 1;
		}


		for (j = m; j >= 1; --j)
			if (dp[n][j]) break;
		maxx = j,i = n,k = 0;
		while (i > 0) {
			
			if (path[i][j] != 0) {

				ans[++k] = i;
				j = j - time[i];
			}
			i = i - 1;
		}


		for (i = k; i >= 1; --i)
			printf("%d ",time[ans[i]]);
		printf("sum:%d\n",maxx);
	}
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值