21.09.12模擬 分割金幣
阿新 • • 發佈:2021-10-07
給定n個數,要求分成兩堆,使得兩堆的和的差值最小的差值和最小差值方案數
一遍揹包即可,求出f_i=湊出和為i的一堆金幣的方案數,那麼湊出tot-f_i的方案數也會是f_i
貪心的從平均分配到不平均分配找即可
#include<iostream> #include<cstdio> #define rep(i,j,k) for(register int i(j);i<=k;++i) #define drp(i,j,k) for(register int i(j);i>=k;--i) #define bug cout<<"~~~~~~~~~~~~~"<<'\n'; #define bugout(x) cout<<x<<endl; typedef long long lxl; template<typename T> inline T max(T &a, T &b) { return a > b ? a : b; } template<typename T> inline T min(T &a, T &b) { return a < b ? a : b; } inline char gt() { static char buf[1 << 21], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; } template <typename T> inline void read(T &x) { register char ch = gt(); x = 0; int w(0); while(!(ch >= '0' && ch <= '9'))w |= ch == '-', ch = gt(); while(ch >= '0' && ch <= '9')x = x * 10 + (ch & 15), ch = gt(); w ? x = ~(x - 1) : x; } template <typename T> inline void out(T x, char cc) { if(x < 0) x = -x, putchar('-'); char ch[20]; int num(0); while(x || !num) ch[++num] = x % 10 + '0', x /= 10; while(num) putchar(ch[num--]); putchar(cc); } const int N = 1007; const int M = 257 * 1007; int n, tot, a[N]; int f[M]; int main() { freopen("divgold.in", "r", stdin); freopen("divgold.out", "w", stdout); read(n); rep(i, 1, n) { read(a[i]); tot += a[i]; } f[0] = 1; rep(i, 1, n) drp(j, tot, a[i]) { f[j] = (f[j] + f[j - a[i]]) % 1000000; }//±³°ü int num = 0, t = 0; drp(j, tot/2,0) { if(f[j]) { t = tot - 2 * j; num = f[j]; break; } } out(t, '\n'); out(num, '\n'); return 0; }
本文來自部落格園,作者:{2519},轉載請註明原文連結:https://www.cnblogs.com/QQ2519/p/15376068.html