题目标题:
A Story on a Sunshine Beach
题目连接:
http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4620
题目类型:
数据结构:
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;
}