AcWing318 划分大理石
题目描述
有价值分别为 的大理石各 块,现要将它们分成两部分,使得两部分价值之和相等,问是否可以实现。
其中大理石的总数不超过 。
大体思路
一类常见的多重背包模型。注意由于两部分的价值之和 ,价值相等则必然说明 为偶数。
然后,我们可以将问题看成:有面额 的纸币 张,问能否组成面额 。直接使用多重背包二进制拆分即可。
代码
#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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本