Codeforces 1032E The Unbearable Lightness of Weights
题目链接
http://codeforces.com/problemset/problem/1032/E
题目大意
给你 $n$ 个砝码,你知道所有的砝码的重量各是多少,你能询问一次是否存在 $K$ 个砝码重量为 $w$。问能确定所有的砝码重量各是多少的最大的 $k$ 是多少。
题目分析
使用动态规划,定义 $f[i][j][k]$ 为已经访问到重量为 $i$ ,有 $j$ 个砝码,总重量为 $k$ 有多少种情况,背包即可。答案即为同样重量的 $k$ 个砝码只有 $1$ 种组合方法的 $k$ 。注意如果只有两种砝码,则全部都可以被识别出来,因为剩下的也都知道是啥了。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int maxn = 105;
int n, m, t;
int a[maxn];
int cnt[maxn];
long long f[2][maxn][maxn * maxn];
int read(){
int x;
scanf("%d", &x);
return x;
}
int main(){
int i, j, k, l;
int ans = 0;
int sum = 0;
n = read();
for(i=1;i<=n;i++){
a[i] = read();
if(!cnt[a[i]]){
m++;
}
sum += a[i];
cnt[a[i]]++;
}
if(m == 2){
printf("%d\n", n);
return 0;
}
f[0][0][0] = 1;
for(i=1;i<=100;i++){
for(k=0;k<=n;k++){
for(j=0;j<=10000;j++){
f[i & 1][k][j] = f[(i - 1) & 1][k][j];
}
}
for(l=1;l<=cnt[i];l++){
for(k=0;k<=n-l;k++){
for(j=0;j<=10000-i*l;j++){
f[i & 1][k + l][j + i * l] += f[(i - 1) & 1][k][j];
}
}
}
}
for(i=1;i<=100;i++){
for(j=1;j<=cnt[i];j++){
if(f[n & 1][j][j * i] == 1){
ans = max(ans, j);
}
if(f[n & 1][n - j][sum - j * i] == 1){
ans = max(ans, j);
}
}
}
printf("%d\n", ans);
return 0;
}