TOJ 4620

来源:互联网 发布:淘宝企业开店保证金 编辑:程序博客网 时间:2024/05/21 19:35


题目标题:

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;}



0 0
原创粉丝点击