POJ 3139 / LA 3693 Balancing the Scale (枚举,状态压缩)

来源:互联网 发布:数控车床螺纹g92编程 编辑:程序博客网 时间:2024/06/05 02:36

传送门:http://poj.org/problem?id=3139


题目大意:给出16个不大于1024数,每个数只使用一次,求使得下列等式成立的方案数。

x1 *  4 + x2 * 3 + x3 * 2 + x4  xx6 * 2 + x7 * 3 + x8 * 4

y1 * 4 + y2 * 3 + y3 * 2 + yyy6 * 2 + y7 * 3 + y8 * 4


思路:G[x]记录的是能够组成和为x的四个数的集合(压缩成一个数表示),枚举四个数的全排列,算出tmp=bit[1]+bit[2]*2+bit[3]*3+bit[3]*4,然后找之前已经求过的也能凑成tmp的四个数的组合,若两者没有重复元素,则可以组成一组无重复的8个数的等式,这里问题就解决了一半了,这时候就可以把能够使等式满足的8个数的每种组合的方案数都求出来,放在state[x]里面保存,最后枚举一遍(0,1<<16),把无重复的两组8个数的组合的方案数相乘后(state[i]*state[((1<<16)-1)^i])累加到ans,由于枚举时候正反会重复,所以最后ans/2就是总共16个数使等式成立的方案数。


感想:位运算和状态压缩可以简化枚举的策略,也有许多意想不到的方便。


Code:


/*   W          w           w        mm          mm             222222222       7777777777777    *//*    W        w w         w        m  m        m  m          222        22              7777    *//*    w        w w         w        m  m        m  m                     22              777     *//*     w      w   w       w        m    m      m    m                    22              77      *//*     w      w    w      w        m    m      m    m                 222                77      *//*      w    w      w    w        m      m    m      m              222                  77      *//*      w    w      w    w        m      m    m      m            222                    77      *//*       w  w        w  w        m        m  m        m         222                      77      *//*       w  w        w  w        m        m  m        m      222                         77      *//*        ww          ww        m          mm          m     222222222222222             77      *///#pragma comment(linker, "/STACK:102400000,102400000")//C++//int size = 256 << 20; // 256MB//char *p = (char*)malloc(size) + size;//__asm__("movl %0, %%esp\n" :: "r"(p));//G++#include<set>#include<map>#include<queue>#include<stack>#include<ctime>#include<deque>#include<cmath>#include<vector>#include<string>#include<cctype>#include<cstdio>#include<cstdlib>#include<cstring>#include<sstream>#include<iostream>#include<algorithm>#define REP(i,s,t) for(int i=(s);i<=(t);i++)#define REP2(i,t,s) for(int i=(t);i>=s;i--)using namespace std;typedef long long ll;typedef unsigned long long ull;typedef unsigned long ul;const int N=20;const int Maxans=10240+10;int a[N];int bit[N];vector<int>G[Maxans];int state[1<<17];bool judge(int x){  int cnt=0;  REP(i,1,16)  {    if(x&(1<<(i-1)))    {      bit[++cnt]=a[i];    }  }  return cnt==4;}int fuck(){  REP(i,0,Maxans)  {    G[i].clear();  }  memset(state,0,sizeof(state));  sort(a+1,a+1+16);  REP(i,0,(1<<16)-1)  {    if(judge(i))    {      do      {        int tmp=bit[1]*1+bit[2]*2+bit[3]*3+bit[4]*4;        for(int j=0;j<G[tmp].size();j++)        {          if((i&G[tmp][j])==0)          {            state[i|G[tmp][j]]++;          }        }        G[tmp].push_back(i);      }while(next_permutation(bit+1,bit+1+4));    }  }  int ans=0;  REP(i,0,(1<<16)-1)  {    ans+=state[i]*state[((1<<16)-1)^i];  }  return ans/2;}int main(){  #ifdef ONLINE_JUDGE  #else    freopen("test.in","r",stdin);  #endif  int ca=1;  while(~scanf("%d",&a[1]))  {    if(!a[1])    {      break;    }    REP(i,2,16)    {      scanf("%d",&a[i]);    }    int ans=fuck();    printf("Case %d: %d\n",ca++,ans);  }  return 0;}


0 0