zoukankan      html  css  js  c++  java
  • SPOJ-SUBSET Balanced Cow Subsets

    嘟嘟嘟spoj
    嘟嘟嘟vjudge
    嘟嘟嘟luogu


    这个数据范围都能想到是折半搜索。
    但具体怎么搜呢?
    还得扣着方程模型来想:我们把题中的两个相等的集合分别叫做左边和右边,令序列前一半中放到左边的数为(a),右边的数为(b),后一半同理为(c)(d)。则我们要找的就是满足(a + c = b + d)的选取方案。
    然后变形(a - b = d - c)。因此我们只要在前一半枚举(a, b),存起来,然后在后一半枚举(c, d),然后查找(d - c)是否出现过。
    注意不是每一个数都要选,所以枚举的时候有三种情况:1.不选。2.选到左边。3.选到右边。所以复杂度为(O(3 ^ {frac{n}{2}}))
    还有一点就是状态判重,这个用二进制表示就行。
    具体实现就是用(map)离散化(a - b),然后因为(a - b)可能由好多种选取方案得来的,所以开一个(vector)记录每一个(a - b)对应的状态。统计答案的时候用一个(bool)数组判重即可。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<map>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define rg register
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 22;
    const int maxp = 1.2e6 + 5;
    inline ll read()
    {
      ll ans = 0;
      char ch = getchar(), last = ' ';
      while(!isdigit(ch)) last = ch, ch = getchar();
      while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
      if(last == '-') ans = -ans;
      return ans;
    }
    inline void write(ll x)
    {
      if(x < 0) x = -x, putchar('-');
      if(x >= 10) write(x / 10);
      putchar(x % 10 + '0');
    }
    
    int n, m;
    ll a[maxn];
    
    int cnt = 0;
    map<int, int> mp;
    vector<int> v[maxp];
    bool vis[maxp];
    
    void dfs1(int stp, ll tot, int now)
    {
      if(stp > m)
        {
          if(mp.find(tot) == mp.end()) mp[tot] = ++cnt;
          v[mp[tot]].push_back(now); return;
        }
      dfs1(stp + 1, tot, now);
      dfs1(stp + 1, tot + a[stp], now + (1 << (stp - 1)));
      dfs1(stp + 1, tot - a[stp], now + (1 << (stp - 1)));
    }
    void dfs2(int stp, ll tot, int now)
    {
      if(stp > n)
        {
          if(mp.find(tot) == mp.end()) return;
          int id = mp[tot];
          for(int i = 0; i < (int)v[id].size(); ++i) vis[v[id][i] | now] = 1;
          return;
        }
      dfs2(stp + 1, tot, now);
      dfs2(stp + 1, tot + a[stp], now + (1 << (stp - 1)));
      dfs2(stp + 1, tot - a[stp], now + (1 << (stp - 1)));
    }
    
    int main()
    {
      n = read(); m = n >> 1;
      for(int i = 1; i <= n; ++i) a[i] = read();
      dfs1(1, 0, 0); dfs2(m + 1, 0, 0);
      int ans = 0;
      for(int i = 1; i < maxp; ++i) ans += (int)vis[i];
      write(ans), enter;
      return 0;
    }
    
  • 相关阅读:
    HubSpot – 网站开发必备的 jQuery 信息提示库
    Ink – 帮助你快速创建响应式邮件(Email)的框架
    Simptip – 使用 Sass 制作的 CSS Tooltip 效果
    字体大宝库:12款好看的手写艺术字体免费下载
    『摄影欣赏』20幅温馨浪漫的精美照片欣赏【组图】
    Stickup – 轻松实现元素固定效果的 jQuery 插件
    精品素材:15套免费的 Photoshop 自定义图形集
    Node.js 入门手册:那些最流行的 Web 开发框架
    潮流设计:15个创意的 3D 字体版式作品欣赏
    值得拥有!精心推荐几款超实用的 CSS 开发工具
  • 原文地址:https://www.cnblogs.com/mrclr/p/10026747.html
Copyright © 2011-2022 走看看