AcWing318 划分大理石

题目描述

有价值分别为 1..6 的大理石各 c1c6 块,现要将它们分成两部分,使得两部分价值之和相等,问是否可以实现。

其中大理石的总数不超过 20000

大体思路

一类常见的多重背包模型。注意由于两部分的价值之和 sum=i×ai,价值相等则必然说明 sum 为偶数。

然后,我们可以将问题看成:有面额 16 的纸币 a1a6 张,问能否组成面额 sum2。直接使用多重背包二进制拆分即可。

代码

#include <bits/stdc++.h>
using namespace std;
#define rep(ii,aa,bb) for(re int ii = aa; ii <= bb; ii++)
#define Rep(ii,aa,bb) for(re int ii = aa; ii >= bb; ii--)
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int, int> PII;
const int maxn = 2e5 + 5;
namespace IO_ReadWrite {
#define re register
#define gg (p1 == p2 && (p2 = (p1 = _buf) + fread(_buf, 1, 1<<21, stdin), p1 == p2) ? EOF :*p1++)
char _buf[1<<21], *p1 = _buf, *p2 = _buf;
template <typename T>
inline void read(T &x){
x = 0; re T f=1; re char c = gg;
while(c > 57 || c < 48){if(c == '-') f = -1;c = gg;}
while(c >= 48 &&c <= 57){x = (x<<1) + (x<<3) + (c^48);c = gg;}
x *= f;return;
}
inline void ReadChar(char &c){
c = gg;
while(!isalpha(c)) c = gg;
}
template <typename T>
inline void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x/10);
putchar('0' + x % 10);
}
template <typename T>
inline void writeln(T x){write(x); putchar('\n');}
}
using namespace IO_ReadWrite;
int n, c[10], w[10], sum;
bool f[maxn];
inline void work(int V) {
Rep(j, sum, V) f[j] |= f[j - V];
}
int main () {
n = 6;
while(1) {
rep(i, 1, n) read(c[w[i] = i]);
if(!(c[1] + c[2] + c[3] + c[4] + c[5] + c[6])) return 0;
sum = 0;
rep(i, 1, n) sum += i * c[i];
if(sum & 1) {
puts("Can't");
continue;
}
memset(f, 0, sizeof f);
f[0] = 1;
rep(i, 1, n) {
for(int k = 1; k <= c[i]; c[i] -= k, k <<= 1) work(k * w[i]);
if(c[i]) work(c[i] * w[i]);
}
puts(f[sum >> 1] ? "Can" : "Can't");
}
return 0;
}
posted @   Mars_Dingdang  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示