• 位运算的一种应用 和 hiho1516过河解题报告


    初始i=s

    每次:i=(i-1) & s

    直到i=0

    etc.
    11000
    10000
    01000
    00000

    10000=10001 & 11000
    01000=01111 & 11000
    00000=00111 & 11000

    etc.
    11110
    11100
    11010
    11000
    10110
    10100
    10010
    10000
    01110
    01100
    01010
    01000
    00110
    00100
    00010
    00000


    证明:
    所有i满足 (s & i)==i,
    且所有满足 (s & i)==i 的数都出现过

    1.
    证明:(s & i)==i
    因为“i=(i’-1) & s”,

    对于i的第t位i(t):

    当s(t)=0时,i(t)=_ & 0 = 0
    _ & 0 = 0

    当s(t)=1时
    1 & i(t) = i(t)

    所以(s & i)==i成立

    2.
    证明:
    所有满足 (s & i)==i 的数都出现过


    对于s中值为0的位 s(t),因为“i=(i’-1) & s”,所以i(t)永远为0

    对于s中值位0的位 s(t),因为“i=(i’-1) & s”,所以i(t)永远不会因为s而影响,所以i(t)的值 为(i’-1)的第t位

    即“(s & i)==i”相当于原来s中的‘1’组成的数字从11…1到00…0每次减少1的变化,而原来s中的‘0’永远不变

    得证


    Usage:
    共有n个人,当前有m个人可以工作,每个人可以被选或不被选,求出这m个人的所有选择情况(用二进制表示)

    Problem:
    hiho1516

    bfs+状态压缩:

    重要的是弄清每次生成新的状态的方法。。。

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <stdbool.h>
      4 
      5 struct node
      6 {
      7     long pos,step,sum;
      8 }q[131073];
      9 //2^16 * 2(两岸)
     10 
     11 long n,cond[3],g[17],num[65537][17];//0为起始岸;1为终止岸;2为船 总数(二进制)
     12 long vis1[17],vis2[17],vis3;
     13 bool vis[65537][2];
     14 
     15 bool judge()
     16 {
     17     long i,j,k;
     18     for (j=0;j<3;j++)
     19     {
     20         for (i=0;i<g[cond[j]];i++)
     21         {
     22             k=num[cond[j]][i];
     23             if (((vis1[k] & cond[j])!=0) && ((vis2[k] & cond[j])==0))
     24                 return false;
     25         }
     26 
     27 //        for (i=0;i<n;i++)
     28 //            if (((cond[j]>>i) & i)!=1)
     29 //                if ( ((vis1[i] & cond[j])!=0)  && ((vis2[i] & cond[j])==0) )
     30 //                    return false;
     31     }
     32     if ((cond[2] & vis3)==0)
     33         return false;
     34     return true;
     35 }
     36 
     37 int main()
     38 {
     39     long m,a,b,c,x,y,head,tail,i,j,k,total,pos,pos_,sum,step,mul[17];
     40     scanf("%ld%ld",&n,&m);
     41     mul[0]=1;
     42     for (i=1;i<=n;i++)
     43         mul[i]=mul[i-1]<<1;
     44     total=(1<<n)-1;
     45     for (i=0;i<=total;i++)
     46     {
     47         g[i]=0;
     48         j=i;
     49         k=0;
     50         while (j>0)
     51         {
     52             if ((j & 1)==1)
     53             {
     54                 num[i][g[i]]=k;
     55                 g[i]++;
     56             }
     57             k++;
     58             j=j>>1;
     59         }
     60     }
     61 
     62     scanf("%ld%ld%ld",&a,&b,&c);
     63     for (i=0;i<n;i++)
     64     {
     65         vis1[i]=0;
     66         vis2[i]=0;
     67     }
     68     vis3=0;
     69     for (i=1;i<=a;i++)
     70     {
     71         scanf("%ld%ld",&x,&y);
     72         vis1[x]+=1<<y;
     73     }
     74     for (i=1;i<=b;i++)
     75     {
     76         scanf("%ld%ld",&x,&y);
     77         vis2[y]+=1<<x;
     78     }
     79     for (i=1;i<=c;i++)
     80     {
     81         scanf("%ld",&x);
     82         vis3+=1<<x;
     83     }
     84     for (i=0;i<65536;i++)
     85         for (j=0;j<2;j++)
     86             vis[i][j]=true;
     87 
     88     head=0;
     89     tail=1;
     90     q[1].pos=0;
     91     q[1].step=0;
     92     q[1].sum=total;
     93     vis[total][0]=false;
     94 
     95     while (head<tail)
     96     {
     97         head++;
     98 
     99         //另外的优化:
    100         //如果在左边,则送尽量多的人到右边
    101         //如果在右边,则送尽量少的人到左边
    102 
    103         //编写程序的简单性:两岸做法的对称性 (Same),从而合二为一
    104 
    105         pos=q[head].pos;
    106         pos_=pos ^ 1;
    107         sum=q[head].sum;
    108         step=q[head].step+1;
    109         //不必取0,前后必会发生变化
    110         for (i=sum;i>0;i=(i-1) & sum)
    111             if (g[i]<=m)
    112              {
    113                  cond[2]=i;
    114                  cond[pos]=sum-i;
    115                  cond[pos_]=total-cond[pos];
    116 
    117                  if (vis[cond[pos_]][pos_]==true && judge()==true)
    118                  {
    119 //                     printf("%ld %ld
    ",cond[pos_],pos_);
    120                      if (pos_==1 && cond[1]==total)
    121                      {
    122                          printf("%ld
    ",step);
    123                          return 0;
    124                     }
    125                     tail++;
    126                     q[tail].pos=pos_;
    127                     q[tail].step=step;
    128                     q[tail].sum=cond[pos_];
    129                     vis[cond[pos_]][pos_]=false;
    130                 }
    131             }
    132     }
    133     printf("-1
    ");
    134     return 0;
    135 }

    /*

    位运算的优势:
    1.相比正常运算极快的运行速度
    2.存储的减少
    3.程序编写的简单(和不容易出错)

    */

  • 相关阅读:
    cocos2dx 动画控制概要
    lua与C交互 具体
    lua与C/C++交互概要
    3D图像算法
    lua 语言笔记
    iostransitiontranslate闪屏问题总结
    document.onreadystatechange()来判断页面加载完
    JavaScript装逼指南
    box-shadow 阴影
    web小技巧
  • 原文地址:https://www.cnblogs.com/cmyg/p/7230998.html
Copyright © 2020-2023  润新知