三角形
涉及知识点:
- 背包dp
solution:
- 背包是dp算法中非常经典的一个问题(如果打算学dp的同学必须要学会背包问题),具体的大家可以看我发在群里的背包九讲pdf
- 关于这道题目,我们可以对每一个宝箱做一个背包
- 题目要求从每一个宝箱中有且只能取一个,所以设dp[i][j]为枚举到第i个宝箱,可以获得钱数等于j的方案数
- 那么转移方程就等于 dp[ i ][ z ] += dp[ i-1 ][ z - a[ i ][ j ] ] ,初始化dp[ 0 ][ 0 ] = 1
- i代表前i个宝箱,z代表可以获得z钱,a[ i ][ j ]代表枚举的第i个宝箱的第j个钱,dp[ i ][ z ]就等于前i个宝箱可以获得z钱的方案数
- j的范围是0~10000,最后从小到达枚举dp[ n ][ j ],代表前n个宝箱中可以获得钱数等于j的方案数,不断和k做差就得到了答案
std:
#include <bits/stdc++.h> using namespace std; #define ll long long const int maxn = 105; int a[maxn][maxn],dp[maxn][maxn*maxn],len[maxn]; int main() { int n , k; cin>>n>>k; for(int i=1;i<=n;i++){ cin>>len[i]; for(int j=1;j<=len[i];j++) cin>>a[i][j]; } dp[0][0] = 1; for(int i=1;i<=n;i++){ for(int z=0;z<=10000;z++){ for(int j=1;j<=len[i];j++){ dp[i][z] += dp[i-1][z-a[i][j]]; } } } ll ans = 0; for(int i=1;i<=10000;i++){ if(dp[n][i] >= k){ ans += 1ll*k*i; break ; }else{ ans += 1ll*dp[n][i]*i; k -= dp[n][i]; } } cout<<ans<<endl; return 0; }
来源:https://www.cnblogs.com/QFNU-ACM/p/12640491.html