题目描述
- 给定一个数组arr,长度为N
- arr中的值不是0就是1
- arr[i]表示第i盏灯的状态,0代表灭灯,1代表亮灯
- 每一栈灯都有开关,但是按下i号灯的开关,会同时改变i-1、i、i+1栈灯的状态
问题二: 如果N盏灯排成一个圈,请问最少按下多少次开关,能让灯都亮起来 排成一个圈
说明:
- i为中间位置时,i号灯的开关能影响i-1、i和i+1 0号灯的开关能影响N-1、0和1位置的灯 N-1号灯的开关能影响N-2、N-1和0位置的灯
题目解析
本题为从左到右尝试模型。
对于所有尝试结果,它有两种可能:
- 本次尝试全亮了
- 本次尝试灯没有全亮
对于这两种可能:
- 对于灯全亮的尝试,我们需要知道本次尝试按了几次按钮。然后从所有全亮的按钮中选出最少的操作次数然后返回
- 如果灯没有全亮,那么说明这个方法不对。因为要求最少的操作次数,我们用MAX来表示这是错误的结果
当然,不管是哪种尝试,我们一定要看遍所有的灯,所有的灯都要去尝试一下,有两种可能:
- 按下开关
- 不按下开关
特别暴力的写法就是从0~N-1的所有灯都去尝试去点灯或者不点灯,然后全部灯都看完了,我们再去遍历一次数组,看灯有没有全亮。
然后我们应该根据某些条件剪枝,否则就是一个全排列了
int loopMinStep(std::vector<int> arr){
if(arr.empty()){
return 0;
}
if(arr.size() == 1){
return arr[0] == 1 ? 0 : 1;
}
if(arr.size() == 2){
return arr[0] != arr[1] ? INT32_MAX : 1;
}
if(arr.size() == 3){
return (arr[0] != arr[1] || arr[0] != arr[2]) ? INT32_MAX : (arr[0] ^ 1);
}
// 0不变,1不变
int p1 = process(arr, 3, arr[1], arr[2], arr[arr.size() - 1], arr[0]);
// 0改变,1不变
int p2 = process(arr, 3, arr[1] ^ 1, arr[2], arr[arr.size() - 1] ^ 1, arr[0] ^ 1);
// 0不变,1改变
int p3 = process(arr, 3, arr[1] ^ 1, arr[2] ^ 1, arr[arr.size() - 1], arr[0] ^ 1);
// 0改变,1改变
int p4 = process(arr, 3, arr[1], arr[2] ^ 1, arr[arr.size() - 1] ^ 1, arr[0]);
p2 = p2 != INT32_MAX ? (p2 + 1) : p2;
p3 = p3 != INT32_MAX ? (p3 + 1) : p3;
p4 = p4 != INT32_MAX? (p4 + 2) : p4;
return std::min( std::min(p1, p2), std::min(p3, p4));
}
// 上一个位置preIndex= nextIndex - 2 , preStatus
// 当前位置curIndex = nextIndex - 1 , curStatus
// 下一个位置,nextIndex
// firstStatus, 0位置的状态
// endStatus, N-1位置的状态
// 返回,让所有灯都亮,至少按下几次按钮
// 当前来到的位置curIndex,一定不能是1!至少从2开始
// nextIndex >= 3
int process(std::vector<int> &arr, int nextIndex, int preStatus, int curStatus, int endStatus, int firstStatus ){
if(nextIndex == arr.size()){// 最后一按钮!
return (endStatus != firstStatus || endStatus != preStatus) ? INT32_MAX : (endStatus ^ 1);
}
// 当前位置,nextIndex - 1
// 当前的状态,叫curStatus
// 如果不按下按钮,下一步的preStatus, curStatus
// 如果按下按钮,下一步的preStatus, curStatus ^ 1
// 如果不按下按钮,下一步的curStatus, arr[nextIndex]
// 如果按下按钮,下一步的curStatus, arr[nextIndex] ^ 1
int noNextPreStatus = 0;
int yesNextPreStatus = 0;
int noNextCurStatus =0;
int yesNextCurStatus = 0;
int noEndStatus = 0;
int yesEndStatus = 0;
if(nextIndex < arr.size() - 1){ // 当前没来到N-2位置
noNextPreStatus = curStatus;
yesNextPreStatus = curStatus ^ 1;
noNextCurStatus = arr[nextIndex];
yesNextCurStatus = arr[nextIndex] ^ 1;
}else if(nextIndex == arr.size() - 1){
noNextPreStatus = curStatus;
yesNextPreStatus = curStatus ^ 1;
noNextCurStatus = endStatus;
yesNextCurStatus = endStatus ^ 1;
noEndStatus = endStatus;
yesEndStatus = endStatus ^ 1;
}
if(preStatus == 0) {
int next = process(arr, nextIndex + 1, yesNextPreStatus, yesNextCurStatus,
nextIndex == arr.size() - 1 ? yesEndStatus : endStatus, firstStatus);
return next == INT32_MAX ? next : (next + 1);
}else {
return process(arr, nextIndex + 1, noNextPreStatus, noNextCurStatus,
nextIndex == arr.size() - 1 ? noEndStatus : endStatus, firstStatus);
}
}