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

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

[复制链接]
发表于 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-11-22 06:10 , Processed in 0.024811 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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