题目描述
商店里有N种药水,每种药水都有一个售价和回收价。小S攒了V元钱,还会M种魔法,可以把一些药水合成另一种药水。他一天可以使用K次魔法,问他一天最多赚多少钱?
输入输出格式
输入格式:
第一行四个数N、M、V、K
接下来N行,每行两个数,表示药水的售价和回收价。
接下来M行,每行若干个数,第一个数表示魔法的成品,第二个数是原料的种数,接下来为各种原料的编号
输出格式:
一个数,表示小S的最大利润
输入输出样例
输入样例#1:
4 2 6 3
1 0
1 0
5 3
20 15
3 2 1 2
4 3 1 2 3
输出样例#1:
12
说明
N<=60 M<=240
V<=1000
k<=30
就是个背包,但是挺麻烦的
跟昊哥一块搞的
先预处理出(v[i][j])表示使用j次魔法后变成第i个物品的花费
这可以用分层 + 背包来做
就是一层一层的更新
求出 v 数组以后直接简单背包一下就好辣
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int M = 245 ;
const int N = 1005 ;
const int INF = 1e9 + 7 ;
using namespace std ;
inline int read() {
char c = getchar() ; int x = 0 , w = 1 ;
while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
return x*w ;
}
int n , m , W , tot ;
int val[M] , cost[M] ;
int v[M][M] , res[M] ;
int temp[M][M] ;
vector < int > p[M] ;
int f[N][M >> 2] ;
inline void Update(int t , int m) {
memset(temp , 63 , sizeof(temp)) ;
temp[0][0] = 0 ;
for(int i = 0 ; i <= m ; i ++)
for(int j = 1 , u ; j < p[t].size() ; j ++) {
u = p[t][j] ;
for(int k = 0 ; k <= i ; k ++) {
temp[j][i] = min(temp[j][i] , temp[j - 1][i - k] + v[u][k]) ;
}
}
v[res[t]][m + 1] = min( v[res[t]][m + 1] , temp[p[t].size() - 1][m] ) ;
for(int i = m + 1 ; i <= tot ; i ++)
v[res[t]][i] = min(v[res[t]][i] , v[res[t]][m + 1]) ;
}
int main() {
n = read() ; m = read() ; W = read() ; tot = read() ;
for(int i = 1 ; i <= n ; i ++) {
val[i] = read() ;
cost[i] = read() ;
for(int j = 0 ; j <= tot ; j ++)
v[i][j] = val[i] ;
}
for(int i = 1 , x , Num ; i <= m ; i ++) {
res[i] = read() ; Num = read() ;
p[i].push_back(0) ;
while(Num -- ) {
x = read() ;
p[i].push_back(x) ;
}
}
for(int i = 1 ; i <= tot ; i ++) // i表示使用i次魔法
for(int j = 1 ; j <= m ; j ++) // 第j种魔法
Update(j , i - 1) ;
// f[i][j] 表示花i元使用j次魔法的收益
// v[i][j] 表示第i个物品使用j次魔法的花费
for(int i = 1 ; i <= W ; i ++)
for(int j = 0 ; j <= tot ; j ++)
for(int k = 1 ; k <= n ; k ++)
for(int l = 0 ; l <= j ; l ++)
if(i - v[k][l] >= 0)
f[i][j] = max(f[i][j] , f[i - v[k][l]][j - l] + (cost[k] - v[k][l]) ) ;
cout << f[W][tot] << endl ;
return 0 ;
}
最新评论