找回密码
 欢迎注册
楼主: 东邪

[讨论] 有多少人参加考试

[复制链接]
发表于 2009-7-22 08:47:02 | 显示全部楼层
一个容易得到的上界是19,开始我猜 ...
shshsh_0510 发表于 2009-7-3 14:59

为什么上界是19呢?很容易得到?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-7-23 09:01:15 | 显示全部楼层
第六感……
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-7-23 10:00:31 | 显示全部楼层
反证20个不行.
如果可以,根据第一个题目的答案可以将20人分成3组.人数最多的两组加起来不少于14人,而14人不能用5道题区分
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-7-23 10:59:50 | 显示全部楼层
1# 东邪
这个题目主要等价状态很多.通过计算机可以考虑下面的算法:
对于给定的k道题目,每道题目3个答案(比如这里k=6),我们依次计算所有n个人构成的集合,其中n个人中任意3个人可以找到一道题目,3个人答案互不相同.
可以看出,n=1的时候,实际上只有一个集合,所有其它的情况都同这个情况等价.
我们的目标就是对于每个n个人构成的集合,在其中添加一个人,构成n+1个人的集合.然后在所有这些n+1个人的集合中,淘汰掉等价的数据.
为了能够淘汰等价的数据,我们需要对每个集合进行一种"标准化".
对于每道题目,其3个答案可以任意置换(只要所有人这个答案的结果同时置换就可以);同样,k道题目的顺序也可以任意置换.而n个人的位置也可以任意置换.
每个集合可以表示成一些k位3进制数.
我们可以对于每个这样的集合,首先计算出通过置换每一位的情况可以得出的集合;这样可以总共有$3^k$个不同的等价集合.
然后我们对这些集合中的n个k位3进制数各自进行排序.但是排序的顺序不是通常的顺序,而是那些各位数通过置换以后能够相互转换的数据要排在一起(也就是它们的顺序不管),比如顺序为
000000, =>0
111111, =>1
222222, =>2
{000001,000010,000100,001000,010000,100000}, =>3
{000002,000020,000200,002000,020000,200000}, =>4
{000003,000030,000300,003000,030000,300000}, =>5
{000012,000102,001002,...., 120000} =>6
...
当然,这样选择以后,$3^k$个集合有些集合会被映射到同样的结果,我们只保留按字典顺序最小的那些表示方式(很有可能只余下一个集合)
然后对于余下的结果,我们再置换k位(k!种不同的置换方式),(这个时候上面各组内部的顺序也要考虑了,找到那个按字典顺序最小的表达方式作为最终标准化结果)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-7-23 14:53:06 | 显示全部楼层
本帖最后由 sheng_jianguo 于 2009-7-23 15:00 编辑
  
.........找到那个按字典顺序最小的表达方式作为最终标准化结果
mathe 发表于 2009-7-23 10:59

当K=6,n=19时,最终标准化的具体结果是怎样的呢?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-7-23 15:10:46 | 显示全部楼层
反证20个不行.
如果可以,根据第一个题目的答案可以将20人分成3组.人数最多的两组加起来不少于14人,而14人不能用5道题区分
mathe 发表于 2009-7-23 10:00


是的,5道题可以区分13人,{4, 4, 5}。人数最多的两组加起来 = 9,4题区分^^
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-7-23 16:36:44 | 显示全部楼层
22# nlrte13
这个还不至于使用第6感把
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-7-23 17:20:16 | 显示全部楼层
试验了一下,发现我上面的标准化过程太花时间了,所以总体上可能比直接重复搜索还要慢
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-7-23 17:27:45 | 显示全部楼层
试验了一下,发现我上面的标准化过程太花时间了,所以总体上可能比直接重复搜索还要慢
mathe 发表于 2009-7-23 17:20


这个就是症结了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-7-24 06:45:31 | 显示全部楼层
5道题目搜索结果好像只有10人.

不过程序好像还有点问题,一到我的cygwin下编译,运行就出错.
谁有空来帮忙调试一下看看:

  1. // muser.cpp : Defines the entry point for the console application.
  2. //

  3. #include "stdafx.h"
  4. #include <assert.h>
  5. #include <stdlib.h>
  6. #include <algorithm>
  7. #include <time.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. using namespace std;
  11. #define K 6
  12. #define KK (1*2*3*4*5*6) //K!
  13. #define M (1<<(2*K))
  14. #define MAX_DEPTH 20
  15. #define TBS ((1<<K)*MAX_DEPTH) //MAX_DEPTH*2^K
  16. int curlist[MAX_DEPTH];
  17. int stdv1[MAX_DEPTH];
  18. int stdv2[MAX_DEPTH];
  19. int curbest=0;
  20. int code[M];
  21. int orders[M];
  22. int indexs[M];
  23. int tc;

  24. int rord[MAX_DEPTH][M];
  25. #ifdef NDEBUG
  26. #define ASSERT(x)
  27. #else
  28. #define ASSERT(x) assert(x)
  29. #endif

  30. #define BEST_STD

  31. int mycmp(const void *p, const void *q)
  32. {
  33.     const int *pi=(const int *)p;
  34.     const int *qi=(const int *)q;
  35.     int i1=*pi,i2=*qi;
  36.     if(code[i1]!=code[i2])
  37.         return code[i1]-code[i2];
  38.     return i1-i2;
  39. }

  40. int tb[TBS][MAX_DEPTH];
  41. int tb2[KK][MAX_DEPTH];
  42. char reorder[6][3]={
  43.     {0,1,2},
  44.     {0,2,1},
  45.     {1,0,2},
  46.     {1,2,0},
  47.     {2,0,1},
  48.     {2,1,0}
  49. };

  50. void best_of_tb_item(int index, int output[], int count)
  51. {
  52.     char a[K];
  53.     int i,j,t;
  54.     for(i=0;i<K;i++)a[i]=i;
  55.     t=0;
  56.     do{
  57.         for(i=0;i<count;i++){
  58.             int u=0;
  59.             for(j=0;j<K;j++){
  60.                 int c=(tb[index][i]>>(2*j))&3;
  61.                 u|=c<<(2*a[j]);
  62.             }
  63.             tb2[t][i]=u;
  64.         }
  65.         qsort(tb2[t],count,sizeof(tb2[t][0]),mycmp);
  66.         t++;
  67.     }while(next_permutation(a,a+K));
  68.     t=0;
  69.     for(i=1;i<KK;i++){
  70.         for(j=0;j<count;j++){
  71.             if(tb2[i][j]!=tb2[t][j])
  72.                 break;
  73.         }
  74.         if(j<count&&indexs[tb2[i][j]]<indexs[tb2[t][j]])
  75.             t=i;
  76.     }
  77.     for(j=0;j<count;j++)output[j]=tb2[t][j];
  78. }

  79. void gen_tb_item(int input[], int output[], int count, char ind[])
  80. {
  81.     int i,j;
  82.     for(i=0;i<count;i++){
  83.         int u=0;
  84.         for(j=0;j<K;j++){
  85.             int c=(input[i]>>(2*j))&3;
  86.             c=reorder[ind[j]][c];
  87.             u|=c<<(2*j);
  88.         }
  89.         output[i]=u;
  90.     }
  91.     qsort(output,count,sizeof(output[0]),mycmp);
  92. }

  93. int find_min_from_table(int total,int count)
  94. {
  95.     int i,j;
  96.     int m=0;
  97.     for(i=1;i<total;i++){
  98.         for(j=0;j<count;j++){
  99.             if(code[tb[i][j]]!=code[tb[m][j]])
  100.                 break;
  101.         }
  102.         if(j<count&&code[tb[i][j]]<code[tb[m][j]]){
  103.             m=i;
  104.         }
  105.     }
  106.     return m;
  107. }

  108. int moving_forward_min(int total,int mid, int count)
  109. {
  110.     int i,j,k;
  111.     if(mid!=0){
  112.         for(j=0;j<count;j++)tb[0][j]=tb[mid][j];
  113.     }
  114.     k=1;
  115.     for(i=mid+1;i<total;i++){
  116.         for(j=0;j<count;j++){
  117.             if(code[tb[i][j]]!=code[tb[0][j]])
  118.                 break;
  119.         }
  120.         if(j==count){
  121.             for(j=0;j<count;j++){
  122.                 tb[k][j]=tb[i][j];
  123.             }
  124.             k++;
  125.         }
  126.     }
  127.     return k;
  128. }

  129. int gen_tb(int input[MAX_DEPTH],int count)
  130. {
  131.     char a[K];
  132.     int i,t,u=0;
  133.     for(i=0;i<count;i++){///The transform that the i'th input is zero
  134.         int v=input[i];
  135.         for(t=0;t<1<<K;t++){
  136.             int h;
  137.             for(h=0;h<K;h++){
  138.                 int s;
  139.                 for(s=0;s<6;s++){
  140.                     if(reorder[s][(v>>(2*h))&3]==0)
  141.                         break;
  142.                 }
  143.                 ASSERT(s<6);
  144.                 if((t&(1<<h))!=0){
  145.                     for(++s;s<6;s++){
  146.                         if(reorder[s][(v>>(2*h))&3]==0)
  147.                             break;
  148.                     }
  149.                 }
  150.                 ASSERT(s<6);
  151.                 a[h]=s;
  152.             }
  153.             gen_tb_item(input,tb[u],count,a);
  154.             u++;
  155.         }
  156.     }
  157.     i=find_min_from_table(u,count);
  158.     return moving_forward_min(u,i,count);
  159. }

  160. void standardize(int input[MAX_DEPTH], int output[MAX_DEPTH], int count)
  161. {
  162. #ifdef BEST_STD
  163.     int best[MAX_DEPTH];
  164.     int cand = gen_tb(input,count);
  165.     best_of_tb_item(0,output,count);
  166.     int i,j;
  167.     for(i=1;i<cand;i++){
  168.         best_of_tb_item(i,best,count);
  169.         for(j=0;j<count;j++){
  170.             if(best[j]!=output[j])
  171.                 break;
  172.         }
  173.         if(j<count&&best[j]<output[j]){
  174.             for(j=0;j<count;j++)best[j]=output[j];
  175.         }
  176.     }
  177. #else
  178.     int i;
  179.     for(i=0;i<count;i++)output[i]=input[i];
  180.     qsort(output,count,sizeof(output[0]),mycmp);
  181. #endif
  182. }

  183. void sort3(char c[3])
  184. {
  185.     char d;
  186.     if(c[0]>c[1]){
  187.         d=c[0];c[0]=c[1];c[1]=d;
  188.     }
  189.     if(c[0]>c[2]){
  190.         d=c[0];c[0]=c[2];c[2]=d;
  191.     }
  192.     if(c[1]>c[2]){
  193.         d=c[1];c[1]=c[2];c[2]=d;
  194.     }
  195. }

  196. void init_order()
  197. {
  198.     char a[K];
  199.     int i,t;
  200.     t=0;
  201.     for(i=0;i<K;i++)a[i]=0;
  202.     do{
  203.         char c[4];
  204.         int u=0;
  205.         int v=0;
  206.         c[0]=c[1]=c[2]=c[3]=0;
  207.         for(i=0;i<K;i++){
  208.             c[a[i]]++;
  209.             u|=a[i]<<(2*i);
  210.         }
  211.         orders[t++]=u;
  212.         //u is original code
  213.         //v is standardized one code
  214.         ASSERT(c[3]==0);
  215.         ///move all 0 to the end of the number
  216.         for(i=c[0];i<c[0]+c[1];i++){///
  217.             v|=1<<(2*i);
  218.         }
  219.         for(i=c[0]+c[1];i<K;i++){
  220.             v|=2<<(2*i);
  221.         }
  222.         code[u]=v;
  223.         for(i=K-1;i>=0;i--){
  224.             if(a[i]<2){
  225.                 a[i]++;
  226.                 break;
  227.             }else{
  228.                 a[i]=0;
  229.             }
  230.         }
  231.         if(i<0)break;
  232.     }while(1);
  233.     tc=t;
  234.     qsort(orders,tc,sizeof(orders[0]),mycmp);
  235.     for(i=0;i<tc;i++){
  236.         indexs[orders[i]]=i;
  237.     }
  238.     for(i=0;i<MAX_DEPTH;i++){
  239.         int j;
  240.         for(j=0;j<tc;j++){
  241.             rord[i][j]=j;
  242.         }
  243.         for(j=0;j<tc;j++){
  244.             int u=rand()%tc;
  245.             if(j!=u){
  246.                 int x=rord[i][j];
  247.                 rord[i][j]=rord[i][u];
  248.                 rord[i][u]=x;
  249.             }
  250.         }
  251.     }
  252. }

  253. void dumpone(int x)
  254. {
  255.     int i;
  256.     for(i=0;i<K;i++){
  257.         printf("%d",(x>>(2*i))&3);
  258.     }
  259. }

  260. void dump(int d)
  261. {
  262.     int i;
  263.     printf("{ ");
  264.     for(i=0;i<d;i++){
  265.         dumpone(curlist[i]);
  266.         printf(" ");
  267.     }
  268.     printf("}\n");
  269. }

  270. void dumpf(FILE *f, int d)
  271. {
  272.     int i;
  273.     for(i=0;i<d;i++){
  274.         fprintf(f,"%d ",curlist[i]);
  275.     }
  276.     fprintf(f,"\n");
  277. }

  278. void search_next(FILE *out, int depth)
  279. {
  280.     int i,j,k,t;
  281.     for(i=0;i<tc;i++){
  282.         int u=orders[i];
  283.         bool p2=true;;
  284.         for(j=0;j<depth;j++){
  285.             if(curlist[j]==u)break;
  286.         }
  287.         if(j<depth)continue;
  288.         for(j=0;j<depth&&p2;j++){
  289.             for(k=j+1;k<depth&&p2;k++){
  290.                 bool pass=false;
  291.                 for(t=0;t<K&&!pass;t++){
  292.                     int a=(curlist[j]>>(2*t))&3;
  293.                     int b=(curlist[k]>>(2*t))&3;
  294.                     int c=(u>>(2*t))&3;
  295.                     if(a!=b&&b!=c&&a!=c){
  296.                         pass=true;
  297.                     }
  298.                 }
  299.                 if(!pass)p2=false;
  300.             }
  301.         }
  302.         if(!p2)continue;
  303.         curlist[depth]=u;
  304.         standardize(curlist,stdv1,depth+1);
  305.         if(stdv1[depth]!=curlist[depth])
  306.             continue;
  307.         dumpf(out,depth+1);
  308.     }
  309. }

  310. void search(int depth,int tt)
  311. {
  312.     if(depth>curbest){
  313.         dump(depth);
  314.         curbest=depth;
  315.     }
  316.     if(depth<MAX_DEPTH-1){
  317.         int i,j,k,t;
  318.         for(i=tt;i<tc;i++){
  319.             int u=orders[i];
  320.             bool p2=true;;
  321.             for(j=0;j<depth&&p2;j++){
  322.                 for(k=j+1;k<depth&&p2;k++){
  323.                     bool pass=false;
  324.                     for(t=0;t<K&&!pass;t++){
  325.                         int a=(curlist[j]>>(2*t))&3;
  326.                         int b=(curlist[k]>>(2*t))&3;
  327.                         int c=(u>>(2*t))&3;
  328.                         if(a!=b&&b!=c&&a!=c){
  329.                             pass=true;
  330.                         }
  331.                     }
  332.                     if(!pass)p2=false;
  333.                 }
  334.             }
  335.             if(!p2)continue;
  336.             curlist[depth]=u;
  337.             standardize(curlist,stdv1,depth+1);
  338.             if(stdv1[depth]!=curlist[depth])
  339.                 continue;
  340.             search(depth+1,i+1);
  341.         }
  342.     }
  343. }

  344. void step_one()
  345. {
  346.     FILE *f=fopen("f0","w");
  347.     fprintf(f,"0");
  348.     fclose(f);
  349. }

  350. char fname[20];
  351. char line[1024];
  352. void step(int i)
  353. {
  354.     int j;
  355.     sprintf(fname,"f%d",i-1);
  356.     FILE *in=fopen(fname,"r");
  357.     sprintf(fname,"f%d",i);
  358.     FILE *out=fopen(fname,"w");
  359.     while(fgets(line,1024,in)){
  360.         char *p=line;
  361.         while(isspace(*p))p++;
  362.         if(*p=='\0')break;
  363.         for(j=0;j<i;j++){
  364.             curlist[j]=atoi(p);
  365.             while(isdigit(*p))p++;
  366.             while(isspace(*p))p++;
  367.         }
  368.         search_next(out, i);
  369.     }
  370.     fclose(in);
  371.     fclose(out);
  372. }

  373. #if 1
  374. int _tmain(int argc, _TCHAR* argv[])
  375. {
  376.     srand(time(NULL));
  377.     init_order();
  378.     curlist[0]=orders[0];
  379.     curbest=1;
  380.     search(1,1);
  381.         return 0;
  382. }
  383. #else
  384. int main()
  385. {
  386.     int i;
  387.     init_order();
  388.     step_one();
  389.     for(i=1;i<MAX_DEPTH-1;i++){
  390.         step(i);
  391.     }
  392. }
  393. #endif
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-20 22:25 , Processed in 0.044578 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表