基于已有知识进行答案猜测的一种问题求解策略。
例如:求小于N的最大素数
找不到一个数学公式,使得根据N就可以计算出这个素数
思考:N-1是素数吗?N-2是素数吗?……N-k是素数吗?
—>判断N-k是否是素数问题,转化为求小于N-k的全部素数。
枚举的思想:
猜测
枚举算法
对问题可能解集合的每一项
根据问题给定的检验条件判定哪些是成立的
使条件成立的即是问题的解
枚举过程
判断猜测的答案是否正确
2是小于N的最大素数吗?
进行新的猜测:有两个关键因素要注意
猜测的结果必须是前面的猜测中没有出现过的.每次猜测是素数一定比已经找到的素数大
猜测的过程中要及早排除错误的答案.除2之外,只有奇数才可能是素数
枚举中三个问题:
给出解空间,建立简洁的数学模型
减少搜索的空间
采用合适的搜索顺序
熄灯问题:
有一个由按钮组成的矩阵,每行有6个按钮,共5行。每个按钮位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边,下边,左边,右边)的灯都会改变一次。(如果灯原来是点亮的,就会被熄灭如果灯原来是熄灭的,则会被点亮)
对矩阵中的每盏灯设置一个初始状态。请你写一个程序,确定需要按下哪些按钮,恰好使得所有的灯都熄灭。
输入:
·第一行是一个正整数N,表示需要解决的案例数
·每个案例由5行组成,每一行包括6个数字
·这些数字以空格隔开,可以是0或1
·0表示灯的初始状态是熄灭的·1表示灯的初始状态是点亮的
输出:
·对每个案例,首先输出一行,输出字符串“PUZZLE#m”,其中m是该案例的序号
·接着按照该案例的输入格式输出5行
·1表示需要把对应的按钮按下
·0表示不需要按对应的按钮
·每个数字以一个空格隔开
思考
:枚举每个按钮的开和关,需要2的30次方。如何减少枚举状态数?基本思路,局部状态确定。每一行的状态都受下面一行的影响。第一行状态固定后,需要熄灭第二行的等灯,第2行的开关起作用后,为了熄灭第2行的灯,第3行的合理开关状态就也是唯一的。以此类推,最后一行的开关状态也是唯一的。一只要第1行的状态定下记作A,那么剩余行的情况就是确定唯一的了。推算出最后一行的开关状态,然后看看最后一行的开关起作用后,最后一行的所有灯是否都熄灭。
·如果是,那么A就是一个解的状态
·如果不是,那么A不是解的状态,第1行换个状态重新试试
所以需要枚举第一行(2的6次方)状态或列。可以使用6层循环。也可以看成二进制状态码。同时我们可以扩充矩阵范围,这样点击角处的按钮情况就便于操作了。5*6矩阵阔成6*8矩阵。
puzzle是矩阵初始状态,press是点击状态,是否点按下一行的按钮,就要判断上一行按钮的状态,上一行按钮状态受初始状态和四周按钮点按的影响。
press[r+1][c]=(puzzle[r][c]+press[r][c-1]+press[r][c]+press[r][c+1]+press[r-1][c])%2
0
# include
int puzzle[6][8], press[6][8];
bool guess(){
int c,r;
for(r=1;r<5;r++) for(c=1;c<7;c++)
press[r+1][c]=(puzzle[r][c]+press[r][c]+press[r-1][c]+press[r][c-1]+press[r][c+1])%2; //根据前一行状态,判断本行是否按
for(c=1;c<7;c++)
if((press[5][c-1]+press[5][c]+press[5][c+1]+press[4][c])%2!=puzzle[5][c])
return(false); //判断最后一行状态,是否全部熄灭
return(true);
}
void enumerate (){ //循环猜的过程
int c; bool success;
for(c=1;c<7;c++)
press[1][c]=0;
while(guess()==false){
press[1][1]++; c=1;
while(press[1][c]>1){
press[1][c]=0;
c++;
press[1][c]++;
}
return;
}
int main(){
int cases,i,r,c; scanf("%d",&cases);
for(r=0;r<6;r++)
press[r][0]=press[r][7]=0;
for(c=1;r<7;r++)
press[0][c]=0;
for(i=0;i
for(r=1;r<6;r++)
for(c=1;c<7;c++)
scanf("%d",&puzzle[r][c]);
enumerate();
printf("PUZZLE #%d\n",i+1);
for(r=1;r<6;r++){
for(c=1;c<7;c++)
printf("%d",press[r][c]);
printf("\n");
}
}
return 0;
}