zoukankan      html  css  js  c++  java
  • 大暴搜 chess

    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

    仔细读题,会发现吃掉敌人点对方案数的贡献很神奇。如果走的空格相同,而走的敌人点不同,对答案无贡献,而对于走的空格相同,但一种走了敌人点,另一种没走,算两个方案。。。。sb出题人语文简直是和我学的。。。。
    可见对于能相互到达的敌人点我们该缩点。也就是说,我们对与这一坨敌人点相连的空格互相连上双向边。(可以互相到达),并把每两个互相到达的空格连上边。
    然后跑spfa,加一个当dis[i]==dis[j]+1时,ans[i]+=ans[j],就行了。
    注意,边不要建多。
    ans不用开ll

    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #define ll long long
    using namespace std;
    inline int read()
    {
        int sum=0;char x=getchar();
        while(x<'0'||x>'9')x=getchar();
        while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}
        return sum;
    }
    struct node{int x,y;}S,T;
    struct road{int v,next;}lu[10000*8];
    queue<node> q;queue<int> Q;
    int n,m,tot,cnt,e;
    int dis[55*55],v[55*55],adj[55*55],al[55*55][55*55];
    int vis[55][55],a[55][55],id[55][55],hh[55][55];
    ll ans[55*55];
    int wz[10][2]={2,1,2,-1,-2,1,-2,-1,1,2,1,-2,-1,2,-1,-2};
    inline bool check(int x,int y){if(x<=0||y<=0||x>n||y>m||a[x][y]==2)return 0;return 1;}
    inline void add(int u,int v){lu[++e]=(road){v,adj[u]};adj[u]=e;}
    void get(node aaa)
    {
        q.push(aaa);cnt=0;memset(hh,0,sizeof(hh));
        while(!q.empty())
        {
            node x=q.front();q.pop();
            for(int i=0;i<8;i++)
            {
                node to;to.x=x.x+wz[i][0],to.y=x.y+wz[i][1];if(!check(to.x,to.y))continue;
                if(a[to.x][to.y]==1&&!vis[to.x][to.y]){q.push(to);vis[to.x][to.y]=1;}
                if(a[to.x][to.y]==0&&!hh[to.x][to.y]){v[++cnt]=id[to.x][to.y];hh[to.x][to.y]=1;}
            }
        }
        for(int i=1;i<=cnt;i++)for(int j=i+1;j<=cnt;j++)
            if(!al[v[i]][v[j]])add(v[i],v[j]),add(v[j],v[i]),al[v[i]][v[j]]=al[v[j]][v[i]]=1;
    }
    void init()
    {
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)id[i][j]=++tot;
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(!a[i][j])
            for(int k=0;k<8;k++)
            {
                int x=i+wz[k][0],y=j+wz[k][1];if(!check(x,y)||a[x][y]!=0)continue;
                add(id[i][j],id[x][y]);//add(id[x][y],id[i][j]);
            }
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(a[i][j]==1&&!vis[i][j])
        {
            vis[i][j]=1;node x;x.x=i,x.y=j;get(x);
        }
    }
    bool spfa()
    {
        int vis[55*55];memset(vis,0,sizeof(vis));memset(dis,40,sizeof(dis));
        Q.push(id[S.x][S.y]);dis[id[S.x][S.y]]=0;
        ans[id[S.x][S.y]]=vis[id[S.x][S.y]]=1;
        while(!Q.empty())
        {
            int x=Q.front();Q.pop();vis[x]=0;
            for(int i=adj[x];i;i=lu[i].next)
            {
                int to=lu[i].v;
                if(dis[to]>dis[x]+1)
                {
                    dis[to]=dis[x]+1;ans[to]=ans[x];
                    if(!vis[to]){vis[to]=1;Q.push(to);}
                }
                else if(dis[to]==dis[x]+1)
                {
                    ans[to]+=ans[x];
                    if(!vis[to]){vis[to]=1;Q.push(to);}
                }
            }
        }
        return dis[id[T.x][T.y]]<100000;
    }
    int main()
    {
        n=read();m=read();
    
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                a[i][j]=read();
                if(a[i][j]==3)S.x=i,S.y=j,a[i][j]=0;
                if(a[i][j]==4)T.x=i,T.y=j,a[i][j]=0;
            }
        init();
        if(!spfa()){cout<<-1;return 0;}
        cout<<dis[id[T.x][T.y]]-1<<endl<<ans[id[T.x][T.y]];
    }
  • 相关阅读:
    四则运算
    3.12----对potplayer的使用评价
    对软件工程的一点思考
    个人附加作业
    附加题
    个人最终总结
    结对编程总结
    修改后的四则运算
    阅读程序回答问题
    Visual studio 2013的安装和单元测试
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632669.html
Copyright © 2011-2022 走看看