題目連結
題目大意
給定 \(N\) 個物品和一個 \(X\) ,第 \(i\) 個物品的重量為 \(ai\),你可以從中選擇任意個物品(不能不選)
假定選擇了 \(S\) 個物品,物品的總重量為 \(V\)
那麼再滿足 \((X - V) \% S = 0\) 的前提下還需要支付 \((X - V) / S\) 的 \(money\)
問最少需要支付多少 \(money\)
解題思路
當 \(S\) 一定時
為滿足 \((X - V) \% S = 0\),則 \(V\) 需滿足 \(V = X \% S\)
為了使支付的 \(money\) 最少, 則 \(V\) 要儘可能大
於是可以列舉 \(S\)
並定義 \(dp[i][j][k]\) 表示從前 \(i\) 個物品中選擇了 \(j\) 個物品使得總重量最大,且這 \(j\) 個物品的總重量 \(\% S = k\)
那麼對於每個物品只有兩種狀態 : 選 \(or\) 不選
於是不難得到 :
\(dp[i][j][k] = dp[i - 1][j][k]\)
\(dp[i][j][k] = dp[i - 1][j - 1][(k - a[i] % S + S) % S] + a[i]\)
最後取最小的 \((X - dp[N][S][X \% S]) / S\) 即可
AC_Code
#include<bits/stdc++.h>
#define rep(i , a , b) for(int i = a ; i <= b ; i ++)
#define int long long
using namespace std;
const int N = 1e2 + 10;
int a[N] , dp[N][N][N];
signed main()
{
int n , x , mi = 1e18;
cin >> n >> x;
rep(i , 1 , n) cin >> a[i];
rep(S , 1 , n)
{
memset(dp , -1 , sizeof(dp));
dp[0][0][0] = 0;
rep(i , 1 , n) rep(j , 0 , S) rep(k , 0 , S - 1)
{
dp[i][j][k] = dp[i - 1][j][k];
if(j > 0 && ~dp[i - 1][j - 1][(k - a[i] % S + S) % S])
dp[i][j][k] = max(dp[i][j][k] , dp[i - 1][j - 1][(k - a[i] % S + S) % S] + a[i]);
}
int res = dp[n][S][x % S];
if(~res) mi = min(mi , (x - dp[n][S][x % S]) / S);
}
cout << mi << '\n';
return 0;
}