a_tx_使天平平衡所需要的最少砝码(滚动数组+取模背包)

现在有n个砝码。第i个砝码的重量为w[i],砝码的左盘可以放任意多个m克的物品(至少放一个),小A希望在右盘放最少的砝码使天平平衡。如果可以做到输出最少的砝码数,不能做到输出-1。

输入:第一行一个 T<5,对于每个T,输入 n,m (n,m<2000)
输入w[0...n-1] (w[i]<200)
输出:每组 T 输出最少砝码数

1
5 6
1 2 3 4 12
输出
1
做盘放2个6克,右盘放1个12克
输入2
2
1 3
2
5 6
1 2 3 4 12
输出
-1
1

暴力背包 40%...

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=2000*300;
int f[N];
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t; cin>>t;
    while (t--) {
        int n, m; cin>>n>>m; //左盘可以放任意多个m克的物品(至少放一个),右盘放最少的砝码使天平平衡。
        memset(f, inf, sizeof f);
        int w[n+1], s=0; for (int i=1; i<=n; i++) cin>>w[i], s+=w[i], f[w[i]]=1;
        f[0]=0;
        for (int i=1; i<=n; i++)
        for (int j=s; j>=w[i]; j--) {
            f[j] = min(f[j], f[j-w[i]] + 1);
        }
        int ans = inf;
        for (int i=1; i*m<=s; i++) {
            if (f[i*m] != inf)
                ans = min(ans, f[i*m]);
        }
        if (ans == inf) cout<<-1<<'\n';
        else cout << ans << '\n';
    }
    return 0;
}
上一篇:洛谷 P6030 - [SDOI2012]走迷宫(高斯消元+SCC 缩点+hack?)


下一篇:C#利用ODP.NET往oracle中高效插入百万数据