TOJ 4620


题目标题:

A Story on a Sunshine Beach


题目连接:

http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4620

题目类型:


动态规划 - 01背包+记录



数据结构:

int g[105][1005] = { 0 },   //记录方案 
	dp[105][1005] = { 0 };

思路分析:

单纯的01背包问题

只不过在输出的时候多了两个条件

一个是输出方案

多申请一组数组来保存方案 

等待全部记录完成后 在终点dp(n,m)往回推即可

另一个条件是 方案数需要根据字典序最小的输出

也就是说 可能存在多种合理的方案

要输出字典序最小的方案


这点可以吧输入和推理背包的顺序颠倒过来

先从第N个背包开始依次处理到第1个背包

输出方案的时候也要遵循这个规则


证明:


源代码:

#include <stdio.h>
#include <iostream>

using namespace std;

struct LMIC_STONE
{
	int w, s;
	
}arr[105];

int n;

int main()
{
	//freopen( "E:\\in.txt", "r", stdin );
	
	int i, j, n, m, t;
	
	scanf( "%d", &t );
	
	while( t -- )
	{
		int g[105][1005] = { 0 },   //记录方案 
			dp[105][1005] = { 0 };
		
		scanf( "%d%d", &n, &m );
		
		for( i = 1; i <= n; i ++ )
		{
			scanf( "%d%d", &arr[i].w , &arr[i].s );
		}
		
		for( i = n; i >= 1; i -- )
		{
			for( j = 0; j <= m ; j ++ )
			{
				if( j - arr[i].w < 0 )
				{
					dp[i][j] = dp[i + 1][j];
					g[i][j] = 0;
					continue;
				}
				
				if( dp[i + 1][j] > dp[i + 1][j - arr[i].w] + arr[i].s )
				{
					dp[i][j] = dp[i + 1][j];
					g[i][j] = 0;
				}
				else
				{
					dp[i][j] = dp[i + 1][j - arr[i].w] + arr[i].s;
					g[i][j] = 1;
				}
			}
		}
		
		printf( "%d\n", dp[1][m] );
		
		bool fir = false;
		
		for( i = 1, j = m; i <= n; i ++ )
		{
			if( g[i][j] )
			{
				if( fir )
				{
					printf( " " );
				}
				
				printf( "%d", i );
				j = j - arr[i].w;
				
				fir = true;
			}
		}
		
		printf( "\n" );
	}
	
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值