题目描述
给定一个字符串str,只由‘X’和‘.’两中国字符构成。
‘X’表示墙,不能放灯,也不需要点亮,‘.’表示居民点,可以放灯,需要点亮。
如果灯放在i位置,可以让i-1,i和i+1三个位置被点亮,返回如果点亮str中所需要点亮的位置,至少需要几盏灯
题目解析
暴力
int process(std::string str, int index, std::set<int> lights){
// index来到结束位置的时候,当前方案准备结束
if(index == str.length()){
// 检查当前方案能否把所有居民楼都照亮
for (int i = 0; i < str.length(); ++i) {
// 当前位置是点的话
if (str[i] != 'X') {
if (!lights.count(i - 1)
&& !lights.count(i)
&& !lights.count(i + 1)) {
return INT32_MAX;
}
}
}
// 经过for循环的检查,任意点的位置都被照亮了,返回当前有效的一种解
return lights.size();
}else{ // str还没结束
// 选择不放灯
int no = process(str, index + 1, lights);
// 只有在i位置是.的时候,才可以选择放灯
int yes = INT32_MAX;
if(str[index] == '.'){
lights.insert(index);
yes = process(str, index + 1, lights);
lights.erase(index);
}
return std::min(no, yes);
}
}
// 纯暴力,用来做对数器。点的位置放灯和不放灯全排列
int minLight(std::string str){
if(str.empty()){
return 0;
}
return process(str, 0, std::set<int>());
}
贪心
int minLight(std::string str){
int i = 0; // i从0出发
int light = 0; // 当前灯的个数
while (i < str.length()){
if(str[i] == 'X'){ // 当前i位置是X,直接跳到下一个位置做决定
i++;
}else{
light++; // i 位置是 . 不管i+1是X还是.当前区域需要放灯
if(i + 1 == str.length()){ //当前是最后一个位置了
break;
}else{
if(str[i + 1] == 'X'){ // 如果i+1位置是X,在i位置放灯,去i+2位置做决定
i = i + 2;
}else{ // i位置是. i+1也是. 那么不管i+2是什么,都在i+1位置放灯,到i+3去做决定
i = i + 3;
}
}
}
}
return light;
}
更简洁的解法
// 两个X之间,数一下.的数量,然后除以3,向上取整
// 把灯数累加
int minLight1(std::string str){
int cur = 0;
int light = 0;
for (char c : str) {
if (c == 'X') {
light += (cur + 2) / 3;
cur = 0;
} else {
cur++;
}
}
light += (cur + 2) / 3;
return light;
}
对数器
std::default_random_engine e;
std::string randomString(int maxLen){
std::uniform_int_distribution<int> distS(0, maxLen);
std::uniform_real_distribution<double > dr;
int size = distS(e);
std::string ans(size, ' ');
for (int i = 0; i < size; ++i) {
ans[i] = dr(e) > 0.5 ? 'X' : '.';
}
return ans;
}
int main() {
int len = 20;
int testTime = 1000;
for (int i = 0; i < testTime; i++) {
std::string test = randomString(len);
int ans1 = minLight(test);
int ans2 = minLight1(test);
if (ans1 != ans2) {
printf("oops!");
return -1;
}
}
printf("finish!");
return 0;
}