看到这个数据范围,显然状压
用\(f[i][j]\)表示开了i个电梯,装的牛的集合为j,每次往最后一台电梯加入牛,让最后一台电梯的重量为\(f[i][j]\)
std::mt19937 r(std::chrono::system_clock::now().time_since_epoch().count());
const int N = 21;
int n, W, w[N];
namespace DP {
int f[19][1 << 19], mx; //¿ªÁËi¸öµçÌÝ£¬Ñ¡ÁËj¼¯ºÏÀïÃæµÄÅ££¬ÖØÁ¿Îªfij
int main() {
memset(f, 0x3f, sizeof f);
mx = (1 << n) - 1;
rep(i, 1, n) {
f[1][1 << (i - 1)] = w[i];
}
rep(i, 1, n) { //µçÌÝÊý
rep(j, 0, mx) {
if(f[i][j] > 1e9) continue;
rep(k, 1, n) {
if(j & (1 << (k - 1))) continue;
if(f[i][j] + w[k] <= W) {
f[i][j | 1 << (k - 1)] = min(f[i][j | 1 << (k - 1)], f[i][j] + w[k]);
} else {
f[i + 1][j | 1 << (k - 1)] = min(f[i][j | 1 << (k - 1)], w[k]);
}
}
}
}
rep(i, 1, n) {
if(f[i][mx] < 1e9) {
out(i, '\n');
break;
}
}
return 0;
}
}
namespace rnd {
int main() {
int t = clock();
int ans(n);
while(clock() - t < CLOCKS_PER_SEC * 0.98)
{
srand(r());
int g(0), num(1);
rep(i, 1, n) {
if(g + w[i] <= W) {
g += w[i];
} else {
g = w[i];
++num;
}
}
ans = min(ans, num);
std::random_shuffle(w + 1, w + n + 1);
}
out(ans, '\n');
return 0;
}
}