Uva OJ 11205 - The broken pedometer

来源:互联网 发布:excel表格自动生成数据 编辑:程序博客网 时间:2024/05/20 13:12

 描述: 输入t,p,n,n个数的显示法

             t 表示有几组测试数据,p表示有多少条显示条,n表示需要显示的数据有多少    (0<=p<=15  0<=n<=99)即有计步器能够表示两个数位的数0~99。

                                                                                  

 

  题意: p 条显示条中能否找到最少的条数便可表示 n 个数(即 找到坏了最多了显示条,也能区分这n个数的最少的没坏的显示条数)

 

用0~2^p的二进制中为1的位数表示该位数的显示条为好的,即用二进制数模拟显示条好坏,再枚举二进制......

 

代码:


#include<iostream>
#include<stdio.h>
#include<string.h>
int hash[100000];                                        // 2 ^ 15 = 32768  < 100000
int frac[20];                                    //fac[0   1   2    3   4  5  6  7  8 9 10……  ]

                                                             //     [1  2^1  2^2  2^3 ……   ……            ] 便于将排列(二进制)化为十进制

int a[120][20];
using namespace std;
int main()
{
     
      int t;
      int p,n,num,sum;
      int min; 
      frac[0]=1;
      int i,j,k,ok;
      for(i=1;i<20;i++)
      {
              frac[i]=2*frac[i-1];
      }
      scanf("%d",&t);
     
      while(t--)
      {
              scanf("%d%d",&p,&n);
              for(i=0;i<n;i++)
              {
                      for(j=0;j<p;j++)
                      {
                              scanf("%d",&a[i][j]);
                      }
              }
              min=1000000000;

             int w=1;
              for(i=0;i<p;i++)    
              {
                              w=w*2;
                              if(w+1>=n)   {w=i;break;}
              }

              for(i=w;i<(1<<p);i++)    
              {  

                   //最开始我从i=0开始(参考别人的)提交后超时,后来发现i至少得表示n位数即2^i>=n才行,所以在之

                   //前先for找到

                   //这个最小i,便可减少时间,提交后便通过了。
                      memset(hash,0,sizeof(hash));
                      num=0;
                      for(k=0;k<p;k++)               // i 中为 的位置表示 用该位作为判不同的某列

                       if(i&(1<<k))                      // 判断此时 中为1的位数
                         num++;
                       ok=1;
                      for(j=0;j<n;j++)                   //将 排列 为 的二进制对应的排列用1标志
                      {
                              sum=0;
                              for(k=0;k<p;k++)
                              if(i&(1<<k))
                                 {
                                          sum+=frac[k]*a[j][k];
                                 }

                                                                 // sum+=2^k * a[j][k]; sum表示一行//排列的十进制表示数字,hash

                                   //标标唯一,当下标为不同数时,a的排列也不同。若下标有相同的,则重

                                    //复,即i位数不能表示N个不同排列

                              if(hash[sum]==0) 
                                  hash[sum]=1;
                              else {ok=0;break; }
                      }
                     
                   
                      if(ok&&num<min) { min=num; }
              }
              printf("%d\n",min);
      }
      return 0;
}

 

 

原创粉丝点击