5 10000 3 1 4 6 2 5 7 3 4 99 1 55 77 2 44 66
255
题意:
某人要买鞋,有k个品牌,每个品牌有j个款,每款都有标价和价值,要求已经M元内,每个品牌至少买一双鞋的最大价值和。
思路:
1. 要求每一组之中至少有一个被选中,和之前的最多有一个稍有区别,需要把题目再次细分。
2. dp[i][j] 表示选定 i 个品牌并且花费为 j 的最大价值,dp[i][j] 为正数表示状态存在,为负数表示状态不存在。
3. dp[i][j] = max(dp[i][j], dp[i][j - vk] + wk); 第 i 类品牌有选择并且要选择第 k 件物品。(不选择第 k 件物品是相等的,所以略过转移方程)
dp[i][j] = max(dp[i][j], dp[i - 1][j - vk] + wk); 第 i 类品牌前面没有选择并且要选择第 k 件物品。
4. 由于状态是从 0 到 i 的且 dp[0][j] = 0,其他为 -INFS 。所以只有当第一类品牌的状态存在时,才能推导出来第二类品牌的存在状态,以此类推。
5. 题目中有 2 个陷阱,一是可能会存在某品牌数量为 0 的情况,另外会存在费用或价格为 0 的情况,所以状态转移方程不能调换。
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <map> #include <string> #include <stack> #include <cctype> #include <vector> #include <queue> #include <set> #include <iomanip> using namespace std; //#define Online_Judge #define outstars cout << "***********************" << endl; #define clr(a,b) memset(a,b,sizeof(a)) #define lson l , mid , rt << 1 #define rson mid + 1 , r , rt << 1|1 #define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++) #define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++) #define REP(i , x , n) for(int i = (x) ; i > (n) ; i--) #define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--) #define mid ((l + r) >> 1) #define mk make_pair const int MAXN = 10000 + 50; const int maxw = 100 + 20; const int MAXNNODE = 1000 +10; const long long LLMAX = 0x7fffffffffffffffLL; const long long LLMIN = 0x8000000000000000LL; const int INF = 0x7fffffff; const int IMIN = 0x80000000; #define eps 1e-8 #define mod 10007 typedef long long LL; const double PI = acos(-1.0); typedef double D; typedef pair<int , int> pii; const D e = 2.718281828459; int dp[12][MAXN] , n , m , k; int cost , value , id; vector <pii> brand[12]; int main() { //ios::sync_with_stdio(false); #ifdef Online_Judge freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif // Online_Judge while(~scanf("%d%d%d" , &n , &m , &k)) { FORR(i , 1 , k)brand[i].clear(); FOR(i ,0 , n) { scanf("%d%d%d" , &id , &cost , &value); brand[id].push_back(make_pair(cost , value)); } clr(dp[0] , 0); int flag = 0; FORR(i , 1 , k) { FORR(j ,0 , m)dp[i][j] = -INF; if(!brand[i].empty())flag++; FOR(j , 0 ,brand[i].size()) { cost = brand[i][j].first; value = brand[i][j].second; REPP(v , m , cost) { dp[i][v] = max(dp[i][v] , dp[i][v - cost] + value); dp[i][v] = max(dp[i][v] , dp[i - 1][v - cost] + value); } } } if(dp[k][m] > 0&& flag == k) printf("%d\n" , dp[k][m]); else printf("Impossible\n"); } return 0; }