cj搜索算法-魔版(打表术失败总结)
今天碰到一个搜索题,题目是:
7.5 魔板
【问题描述】
有这样一种魔板:它是一个长方形的面板,被划分成n行m列的n*m个方格。每个方格内有一个小灯泡,灯泡的状态有两种(亮或暗)。我们可以通过若干操作使魔板从一个状态改变为另一个状态。操作的方式有两种:
(1)任选一行,改变该行中所有灯泡的状态,即亮的变暗、暗的变亮;
(2)任选两列,交换其位置。
当然并不是任意的两种状态都可以通过若干操作来实现互相转化的。
你的任务就是根据给定两个魔板状态,判断两个状态能否互相转化。
【输入】
文件中包含多组数据。第一行一个整数k,表示有k组数据。
每组数据的第一行两个整数n和m。(0<n,m≤100)
以下的n行描述第一个魔板。每行有m个数字(0或1),中间用空格分隔。若第x行的 第y个数字为0,则表示魔板的第x行y列的灯泡为“亮”;否则为“暗”。
然后的n行描述第二个魔板。数据格式同上。
任意两组数据间没有空行。
【输出】
共k行,依次描述每一组数据的结果。
若两个魔板可以相互转化,则输出YES,否则输出NO。(注意:请使用大写字母)
【样例】
panel.in
2
3 4
0 1 0 1
1 0 0 1
0 0 0 0
0 1 0 1
失败总结:
最最主要的是,偷懒,选择了打表术.....一开始觉得打表术简单,结果是很多情况都没有考虑到,整节晚自习都在考虑完善打表术,结果后面发现打表术根本行不通!
详细:
1.一开始以为只要每行的0的个数符合一定条件就可以了,但是发现列也要改;
2.以为列0的数量符合条件就好了,结果发现顺序也是个问题;
3.用string改好顺序了,结果发现判断并不容易;
4.判断好了,发现 如果一行的0的个数等于m div 2 时,要分类讨论..............
然后,就超级复杂........
教训:碰到搜索题最好不要用打表术!如果用打表术一定要考虑周全!
不要偷懒!不要鼠目寸光!!!!!!!!!
附:我的失败代码:
1 program panel; 2 var 3 s:array[1..200,1..200] of integer; 4 jin:array[1..200]of integer; 5 num2,num3:array[1..200]of string; 6 st1,st2:string; 7 w:array[1..200] of longint; 8 boo:array[1..200]of boolean; 9 num:array[1..200] of longint; 10 i,j,k,l,h,m,n,q,t:longint; 11 bool,bool2:boolean; 12 begin 13 assign(input,'panel.in'); 14 assign(output,'panel.out'); 15 reset(input); 16 rewrite(output); 17 read(k); 18 for q:=1 to k do 19 begin 20 fillchar(s,sizeof(s),0); 21 fillchar(num,sizeof(num),0); 22 bool:=true; 23 read(n,m); 24 for i:=1 to 2*n do 25 for j:=1 to m do 26 begin 27 read(s[i,j]); 28 if s[i,j]=0 then inc(num[i]); 29 end; 30 i:=1; 31 while((num[i]=num[i+n])or(num[i]+num[i+n]=m))and(i<=n)do 32 begin 33 inc(i); 34 if ((num[i]<>num[i+n])and(num[i]+num[i+n]<>m))and(i<=n) 35 then bool:=false; 36 end; 37 if not bool then writeln('NO') 38 else 39 begin 40 h:=0; 41 for i:=1 to n do 42 if num[i]=m div 2 then begin inc(h); w[h]:=i; end; 43 for i:=1 to n do 44 begin 45 if (num[i]<>num[i+n])and(num[i]+num[i+n]=m) then 46 begin 47 for j:=1 to m do 48 if s[i,j]=0 then s[i,j]:=1 49 else s[i,j]:=0; 50 end; 51 end; 52 bool2:=true; 53 for i:=1 to m do 54 delete(num2[i],1,length(num2[i])); 55 for i:=1 to m do 56 delete(num3[i],1,length(num3[i])); 57 for j:=1 to m do 58 for i:=1 to n do 59 num2[j]:=num2[j]+chr(s[i,j]+48); 60 for j:=1 to m do 61 for i:=n+1 to 2*n do 62 num3[j]:=num3[j]+chr(s[i,j]+48); 63 j:=0; 64 fillchar(boo,sizeof(boo),true); 65 bool2:=true; 66 repeat 67 inc(j); 68 t:=0; 69 repeat 70 inc(t); 71 if (num2[j]=num3[t])and(boo[t])then boo[t]:=false; 72 until((num2[j]=num3[t]))or(t>=m); 73 if (num2[j]<>num3[t])and(j<=m) 74 then bool2:=false; 75 until (num2[j]<>num3[t]) or (j>=m); 76 if not bool2 then 77 begin 78 inc(jin[1]); 79 e:=1; 80 while jin[e]=2 do begin jin[e]:=0; inc(e); inc(jin[e]) end; 81 if w[h+1]=1 then write('NO') 82 else begin 83 for i:=1 to h do 84 if w[h]=1 then 85 begin{到这里就变得很复杂了!} 86 end; 87 end; 88 else writeln('YES'); 89 end; 90 end; 91 close(input); 92 close(output); 93 end.
记住教训啊!
2012-10-09