题目链接:
扫雷2并不科学(见扫雷3里的第一个提示,)然后就没写了- -
思路:
扫雷一:
只有一行
枚举第一个格子为有雷 或者 没有雷
然后再往下搜索 得到多个可行解
所有可行解的某个位置都为雷的一定为雷
所有可行解的某个位置都不为为雷的一定为不为雷
扫雷三:思路1:未知的位置只有不超过10个,直接爆力枚举所有未知的位置
得到多个可行解
所有可行解的某个位置都为雷的一定为雷
所有可行解的某个位置都不为为雷的一定为不为雷
思路2:根据条件1:.如果某一个被探明的格子里所标的数字为0,那么它相邻的8个格子里的未探明格子被认作是一定不是地雷的格子。
和条件2:如果某一个被探明的格子里所标的数字为K,且它相邻的8个格子里正好有K个没有探明的格子的话,则这K个没有探明的格子被认作是一定是地雷的格子。
反复处理 可以得出全部完整的地图(输出答案)
或 一副部分完整的地图
然后再 搜索枚举所有未知的位置为有雷或者没有雷
得到多个可行解
所有可行解的某个位置都为雷的一定为雷
所有可行解的某个位置都不为为雷的一定为不为雷
扫雷1代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100050
using namespace std;
int ans[105][maxn];
int mine[maxn];
int ans1[maxn],ans2[maxn];
int d[maxn];
int n;
int s;
void dfs(int loc)
{
if(loc==n+1)
{
if(mine[loc-1]==d[loc-2]+d[loc-1])
{
s++;
for(int i=1; i<=n; i++)
ans[s][i]=d[i];
}
return;
}
if(mine[loc-1]==d[loc-2]+d[loc-1])
{
d[loc]=0;
dfs(loc+1);
}
else if(mine[loc-1]==d[loc-2]+d[loc-1]+1)
{
d[loc]=1;
dfs(loc+1);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
s=0;
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&mine[i]);
d[0]=d[1]=0;
dfs(2);
d[0]=0;
d[1]=1;
dfs(2);
int s1=0,s2=0;
if(s==1)
{
for(int j=1;j<=n;j++)
{
if(ans[1][j]==0)
ans1[s1++]=j;
else
ans2[s2++]=j;
}
}
else
{
for(int j=1;j<=n;j++)
{
if(ans[1][j]==0&&ans[2][j]==0)
ans1[s1++]=j;
else if(ans[1][j]==1&&ans[2][j]==1)
ans2[s2++]=j;
}
}
printf("%d",s2);
for(int i=0;i<s2;i++)
printf(" %d",ans2[i]);
cout<<endl;
printf("%d",s1);
for(int i=0;i<s1;i++)
printf(" %d",ans1[i]);
cout<<endl;
}
return 0;
}
扫雷3代码1:
#include<cstdio>
//-2no -3yes
int s[12][12];
int a[10][2];
int f[10];
int n,m,le;
int remain[12][12];
bool check(int k)
{
int i,j,sum;
int x=a[k][0];
int y=a[k][1];
for(i=0;i<9;i++)
if(remain[x+i/3-1][y+i%3-1]==0)
return false;
return true;
}
void work(int k)
{
int i,j;
int x=a[k][0];
int y=a[k][1];
if(k<le)
{
if(check(k))
{
s[x][y]=-3;
for(i=0;i<9;i++)
if(remain[x+i/3-1][y+i%3-1]>0)
remain[x+i/3-1][y+i%3-1]--;
work(k+1);
for(i=0;i<9;i++)
if(remain[x+i/3-1][y+i%3-1]>=0)
remain[x+i/3-1][y+i%3-1]++;
}
s[x][y]=-2;
work(k+1);
}
else
{
for(i=0;i<le;i++)
for(j=0;j<9;j++)
if(remain[a[i][0]+j/3-1][a[i][1]+j%3-1]>0)
return;
for(i=0;i<le;i++)
if(f[i]==0)
f[i]=s[a[i][0]][a[i][1]];
else if(f[i]!=s[a[i][0]][a[i][1]])
f[i]=-1;
}
}
int main(){
int i,j,t,ans1,ans2;
scanf("%d",&t);
while(t--){
le=0;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&s[i][j]);
if(s[i][j]==-1)
{
a[le][0]=i;
a[le][1]=j;
le++;
}
}
for(i=0;i<=n+1;i++){
s[i][0]=-2;
s[i][m+1]=-2;
}
for(j=0;j<=n+1;j++){
s[0][j]=-2;
s[n+1][j]=-2;
}
for(i=0;i<le;i++)
f[i]=0;
for(i=0;i<=n+1;i++)
for(j=0;j<=m+1;j++)
remain[i][j]=s[i][j];
work(0);
ans1=0;ans2=0;
for(i=0;i<le;i++)
if(f[i]==-3)
ans1++;
else if(f[i]==-2)
ans2++;
printf("%d %d\n",ans1,ans2);
}
return 0;
}
扫雷3代码2:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 210
using namespace std;
struct node
{
int x,y,d;
};
queue<node>q;
int map[maxn][maxn];
int remain[maxn][maxn];
int n_know[maxn][maxn];
int possible[maxn][2],possible_num;
int dir[8][2]= {1,0,-1,0,0,1,0,-1, 1,1,1,-1,-1,1,-1,-1};
int n,m;
int ans1,ans2;
int no_know;
int f[maxn];
void update(int x,int y,int d) //更新remain 如果满足条件一二则继续处理
{
int tx,ty;
for(int i=0; i<8; i++)
{
tx=x+dir[i][0];
ty=y+dir[i][1];
if(x<1||y<1||x>n||y>m)
continue;
if(map[tx][ty]>=1&&map[tx][ty]<=8&&d==0)
{
n_know[tx][ty]--;
if(n_know[tx][ty]==remain[tx][ty])
q.push( {tx,ty,map[tx][ty]});
}
if(map[tx][ty]>=1&&map[tx][ty]<=8&&d==1)
{
remain[tx][ty]--;
n_know[tx][ty]--;
if(remain[tx][ty]==0)
q.push( {tx,ty,0});
}
}
}
int judge(int x,int y,int d) //d=-1:统计n_know 0:条件1 1~8:条件2
{
int tx,ty,s=0;
for(int i=0; i<8; i++)
{
tx=x+dir[i][0];
ty=y+dir[i][1];
if(x<1||y<1||x>n||y>m)
continue;
if(map[tx][ty]==-1&&d==-1)
s++;
if(map[tx][ty]==-1&&d==0)
{
map[tx][ty]=10;
ans1++;
no_know--;
update(tx,ty,0);
}
if(map[tx][ty]==-1&&d>=1&&d<=8)
{
map[tx][ty]=-2;
ans2++;
no_know--;
update(tx,ty,1);
}
}
if(d==-1)
return s;
}
bool check(int k)
{
int x=possible[k][0];
int y=possible[k][1];
for(int i=0; i<9; i++)
if(remain[x+i/3-1][y+i%3-1]==0)
return false;
return true;
}
void dfs(int loc)
{
int x=possible[loc][0];
int y=possible[loc][1];
if(loc<possible_num)
{
if(check(loc))
{
map[x][y]=-2;
for(int i=0; i<9; i++)
if(remain[x+i/3-1][y+i%3-1]>0)
remain[x+i/3-1][y+i%3-1]--;
dfs(loc+1);
for(int i=0; i<9; i++)
if(remain[x+i/3-1][y+i%3-1]>=0)
remain[x+i/3-1][y+i%3-1]++;
}
map[x][y]=10;
dfs(loc+1);
}
else
{
for(int i=0; i<possible_num; i++)
for(int j=0; j<9; j++)
if(remain[possible[i][0]+j/3-1][possible[i][1]+j%3-1]>0)
return;
for(int i=0; i<possible_num; i++)
if(f[i]==0)
f[i]=map[possible[i][0]][possible[i][1]];
else if(f[i]!=map[possible[i][0]][possible[i][1]])
f[i]=-1;
}
}
void work()
{
node head;
while(!q.empty())
{
head=q.front();
q.pop();
judge(head.x,head.y,head.d);
}
if(no_know==0)
cout<<ans2<<" "<<ans1<<endl;
else //地图未完整
{
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
if(map[i][j]==-1)
possible[possible_num][0]=i,possible[possible_num++][1]=j;
dfs(0);
for(int i=0; i<possible_num; i++)
if(f[i]==10)
ans1++;
else if(f[i]==-2)
ans2++;
cout<<ans2<<" "<<ans1<<endl;
// for(int i=1;i<=n;i++){
// for(int j=1;j<=m;j++)
// printf("%4d",map[i][j]);
// cout<<endl;
// }
}
}
void init()
{
memset(f,0,sizeof(f));
while(!q.empty())
q.pop();
ans1=ans2=0;
no_know=0;
possible_num=0;
for(int i=0; i<=n+1; i++)
{
map[i][0]=10;
map[i][m+1]=10;
}
for(int j=0; j<=n+1; j++)
{
map[0][j]=10;
map[n+1][j]=10;
}
}
int main()
{
freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
scanf("%d",&map[i][j]);
remain[i][j]=map[i][j];
if(map[i][j]==-1)
no_know++;
}
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
n_know[i][j]=judge(i,j,-1);
if(remain[i][j]==0||remain[i][j]==n_know[i][j])
q.push({i,j,map[i][j]});
}
work();
}
return 0;
}
//我简直是有强迫症.....