扫雷算法

所谓扫雷首先一个简单只有一行啊 a[i]=a[i-1]-vis[i-1]-vis[i-2]

通过二元一次方程 正推

#include<bits/stdc++.h>
using namespace std;
#define LOACL  freopen("in","r",stdin);\
            freopen("out","w",stdout); 

const int  inf = 987654321;
const int sz = 1e6 + 5;
const int mod = 1e9 + 7;
const int sqrtn = 300; 

#define add(u,v,w) (e[++tot]=(edge){v,head[u],1},head[u]=tot;) 
#define f(i,l,r) for(int i=l;i<=r;++i)
#define g(i,l,r) for(int i=l;i>=r;--i)
#define CLR(arr,val) memset(arr,val,sizeof(arr)) 
typedef long long ll; 
int n,a [2][sz];
int arr[sz],b0[sz],b1[sz],ans0[sz],ans1[sz];
bool f0,f1;
void slove()
{
    f0=f1=true;
    b0[1]=0;
    b0[1]=1;
    f(i,2,n)
    {
        if(f0)
        {
            b0[i]=arr[i-1]-b0[i-1]-b0[i-2];
            if(b0[i]<0||b0[i]>1)f0=false;
        }
        if(f1)
        {
            b1[i]=arr[i-1]-b1[i-1]-b1[i-2];
            if(b1[i]<0||b1[i]>1)f1=false;
        }
    }
    if(arr[n]!=b0[n]+b0[n-1])
        f0=false;
    if(arr[n]!=b1[n]+b1[n-1])
        f1=false;
    
}
int main()
{
    LOACL
    int t;
    cin>>t;
    while(t--)
    {
        CLR(a,0);

        cin>>n;
        f(i,1,n)cin>>arr[i];
        slove();
        int cnt0 =0,cnt1=0;
        if(f0  && f1)
        {
            f(i,1,n)
            {
                if(b0[i]==1 && b1[i]==1)
                {
                    ans1[cnt1++]=i ;
                }
                else if  (b0[i]==0 && b1[i]==0)    
                ans0[cnt0++]=i ;    
            }    
        }
        else if(  f1 )
        {
            f(i,1,n)
            if (b1[i] == 1)  
                ans1[cnt1++] = i;  
            else  
                ans0[cnt0++] = i;  
        }
        else if(  f0 )
        {
            f(i,1,n)
            if (b0[i] == 1)  
                ans1[cnt1++] = i;  
            else  
                ans0[cnt0++] = i;  
        }
        cout<<cnt1;
        f(i,0,cnt1-1)cout<<" "<<ans1[i];cout<<endl;
        cout<<cnt0;
        f(i,0,cnt0-1)cout<<" "<<ans0[i];cout<<endl;


    }
    return 0;
}
View Code

 

多维:

情况一 中心为0 四周都是安全区域

情况二: 中心数 等于 未知区域 那么都是地雷

情况三: 中心数 和其边缘的那个已知数字 满足 a-b= c(a)-c(b) 那么非交界都是雷

 #include<bits/stdc++.h>
 using namespace std;
 #define LOACL  freopen("in","r",stdin);\
             freopen("out","w",stdout); 
 
 const int  inf = 987654321;
 const int sz = 1e6 + 5;
 const int mod = 1e9 + 7;
 const int sqrtn = 300; 
 
 #define add(u,v,w) (e[++tot]=(edge){v,head[u],1},head[u]=tot;) 
 #define f(i,l,r) for(int i=l;i<=r;++i)
 #define g(i,l,r) for(int i=l;i>=r;--i)
 #define CLR(arr,val) memset(arr,val,sizeof(arr)) 
 typedef long long ll; 
 int n,m;
 int a[201][201];
 int cnt0,cnt1 ;
 int calc(int x,int y)
 {
     int count=0;
     f(i,-1,1) if(x+i>=1&&x+i<=n)
     f(j,-1,1) if(y+j>=1&&y+j<=m &&a[x+i][y+j] <0)
     count++;
     return count;
 }
 bool  isnxt(int x,int y,int i,int j)
 {
     if((x-i)>1||(x-i)<-1||(y- j)>1||(y- j)<-1) return  false;
     return true ;
 }
 
  
  bool check(int x,int y,int c,int d)
 {
     f(i,-1,1) if(x+i>=1&&x+i<=n)
     f(j,-1,1) if(y+j>=1&&y+j<=m &&a[x+i][y+j] < 0 &&!isnxt(x+i,y+j,c,d))
     return false ;
     return true;
 }
 void run(int x,int y)
 {
     f(i,-1,1) if(x+i>=1&&x+i<=n)
     f(j,-1,1) if(y+j>=1&&y+j<=m &&a[x+i][y+j] == -1)
     a[x+i][y+j] =-2;
 } 
 void run2(int x,int y)
 {
     if(calc(x,y)==a[x][y])
     f(i,-1,1) if(x+i>=1&&x+i<=n)
     f(j,-1,1) if(y+j>=1&&y+j<=m &&a[x+i][y+j] <0 )
     a[x+i][y+j] =-3;
 } 
 void run3(int x,int y)
 {
     f(c,-2,2)  if(x+c>=1&&x+c<=n)
    f(d,-2,2) 

    if(y+d>=1&&y+d<=m && (c||d)&&a[x+c][y+d]>=0 && check(x+c,y+d,x,y))
    {
        if(a[x][y]-a[x+c][y+d] == calc(x,y)-calc(x+c,y+d))
        {
                f(i,-1,1) if(x+i>=1&&x+i<=n)
                 f(j,-1,1) if(y+j>=1&&y+j<=m && a[x+i][y+j]<0 &&!isnxt(x+i,y+j,x+c,y+d))
                 a[x+i][y+j] =-3;
        }
    }
 }
  
 int main()
 {
     LOACL
     int t;
     cin>>t;
     while(t--)
     {
         cin>>n>>m;
         f(i,1,n) f(j,1,m) cin>>a[i][j];
         f(i,1,n) f(j,1,m)
         {
             if(!a[i][j])run(i,j);
             if(a[i][j]>0) run2(i,j),run3(i,j);
         }
         cnt0=cnt1=0;
         f(i,1,n) f(j,1,m)
         {
             if(a[i][j]==-2) cnt0++;
             if(a[i][j]==-3) cnt1++; 
         }
         cout<<cnt1<<" "<<cnt0<<endl;
     }     
     return 0;
 }
View Code

 

转载于:https://www.cnblogs.com/corx/p/8569636.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值