您的位置:首页 > 其它

【算法学习笔记】76.DFS 回溯检测 SJTU OJ 1229 mine

2015-07-20 15:54 134 查看
扫雷玩得好还是有点好处的......

这个题一开始像从后向前按照第一排的数字进行DFS 发现自己真傻,先不说这种情况下每个数字的填写情况很多, 还要处理相邻位置的问题。

所以可以对每一位有没有地雷进行枚举。处理每一位的时候,要保证上一个数字是合理的,否则不用进行下去了,类似回溯,注意have变量的处理就好了。

#include <iostream>
#include <stack>
using namespace std;
//最长 暗示dfs
//遇到3 和 0 其实只有一种情况
//遇到2 和 1 有三种情况
//遇到* 有 2+2*3 = 8种情况,
//可见如果以数字为dfs的条件的话 很麻烦 还不如直接用0 1 来枚举每个炸弹的位置
//其实如果数据小的话 可以直接遍历所有可能解 然后进行验证 但是因为n过大,全部情况根本没有办法枚举完,另外就是验证的效率很低
//所以还是dfs

int n;
string nums;
bool isMine[100000+10]={false};
void init(){
cin>>n;
cin>>nums;
}
bool have = false;

int alreadyHave(int cur){
int res = 0;
res += isMine[cur];
if(cur>0)
res += isMine[cur-1];
if(cur<n-1)
res += isMine[cur+1];
return res;
}

bool canPut(int cur){
if(nums[cur]=='*')
return true;
else
return ('0' + alreadyHave(cur) ) <= nums[cur];
}
bool exactPut(int cur){
if(nums[cur]=='*')
return true;
else
return ('0' + alreadyHave(cur) ) == nums[cur];
}

void dfs(int cur){
if(have)
return;
if(cur<0){
have = exactPut(0);
return;
}
isMine[cur] = true;
if((cur == n-1 and canPut(cur))
or (cur<n-1 and exactPut(cur+1)) )
dfs(cur-1);

if(have)//不必继续
return;

isMine[cur] = false;
if((cur == n-1 and canPut(cur))
or (cur<n-1 and exactPut(cur+1)) )
dfs(cur-1);
return;
}

void build(){

dfs(n-1);
int ans = 0;
for (int i = 0; i < n; ++i)
{
if(isMine[i])
ans++;
}
cout<<ans<<endl;
for (int i = 0; i < n; ++i)
{
cout<<isMine[i];
}
cout<<endl;
}

int main(int argc, char const *argv[])
{
init();
build();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: