zoukankan      html  css  js  c++  java
  • 贪食蛇(未完待续)

    题解:

    练代码功底的题目

    首先思路嘛很显然 spfa+状压dp(你要说爆搜也可以)

    令f[i][j][s][k]表示当前在i,j,蛇的形状为s,然后吃到的状态是k

    然后呢细节一大堆

    首先空间就是个问题

    12*12*2^12*2^4

    (为什么是2^14次方呢 因为可以记录相邻之间的关系有4种,然后最多要记录6个,我代码里写的是7个。。最后一次的那个是不用记得)

    然后还要输出方案 如果是记6个的话应该可以随便开

    如果记7个的话 那就搞一个int记录前面蛇的状态,两个bool记录蛇的位置(因为只有1-4)

    然后颜色是要当时算的

    这样勉强512mb卡过去。。

    时间上嘛理论是(x=12*12*2^12*2^4) xlogx的

    但因为挺多状态是冗余的 应该是够得。。

    然后我觉得洛谷上的评测可能是单一答案么。。。 所以只拿了no solution的分

    以后再看看。。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn1 16390
    #define maxn2 15
    int dp[13][13][maxn1][maxn2],w[16][16],ft[16][16];
    int pre[13][13][maxn1][maxn2];
    bool pre2[3][13][13][maxn1][maxn2];
    bool ff[16][16][maxn1][maxn2];
    int dx[5]={0,1,-1,0,0};
    int dy[5]={0,0,0,1,-1};
    int n,m,k;
    int jl[1000000];
    struct re{
        int a,b,c,d;
    };
    queue<re> q;
    int js(int x,int y,int x1,int y1)
    {
        if (x1==x+1) return(0);
        if (x1==x-1) return(3);
        if (y1==y+1) return(2);
        if (y1==y-1) return(1);
    }
    int query(int x)
    {
        int cnt=4;
        for (int i=1;i<=4;i++)
          if (x>>i&1) cnt++;
        return(cnt);
    }
    bool pd(re tmp,int i)
    {
        int x=tmp.a,y=tmp.b,now=tmp.c;
        int x1=x+dx[i],y1=y+dy[i];
        if (x1<=0||y1<=0||x1>n||y1>m||w[x1][y1]==0) return(false); 
        int len=query(tmp.d);
        for (int i=1;i<len;i++)
        {
            int tmp=now-((now>>2)<<2);
            now>>=2;
            if (tmp==0) x++;
            if (tmp==3) x--;
            if (tmp==2) y++;
            if (tmp==1) y--;
            if (x1==x&&y1==y) return(false);
        }
        return(true);
    }
    re js2(re tmp,int i)
    {
        int x=tmp.a,y=tmp.b;
        if (ft[x+dx[i]][y+dy[i]])
        {
            int x1,x2=tmp.d|(1<<(ft[x+dx[i]][y+dy[i]]-1));
            x1=(tmp.c<<2)+js(x+dx[i],y+dy[i],x,y);
            re x3={x1,x2};
            return(x3);
        }
        int now=tmp.c,cnt=0,len=query(tmp.d);
        for (int j=1;j<len;j++)
        {
            now>>=2;
            cnt+=2;
        }
        re x3={((tmp.c-(now<<cnt))<<2)+js(x+dx[i],y+dy[i],x,y),tmp.d};
        return(x3);
    }
    char c[100];
    #define INF 1e9
    int main()
    {
        freopen("noi.in","r",stdin);
        freopen("noi.out","w",stdout);
        std::ios::sync_with_stdio(false);
        cin>>n>>m;
        for (int i=1;i<=n;i++)
        {
            cin>>c;
            for (int j=1;j<=m;j++) w[i][j]=c[j-1]-'0';
        }
        int x,y,x2,y2;
        cin>>x>>y; x2=x; y2=y; int tmp=0;
        for (int i=1;i<=3;i++)
        {
            int x1,y1;
            cin>>x1>>y1;
            tmp+=js(x,y,x1,y1)<<(2*(i-1));
            x=x1; y=y1;
        }
        memset(dp,-1,sizeof(dp));
        dp[x2][y2][tmp][0]=0;
        pre[x2][y2][tmp][0]=-1;
        re x4={x2,y2,tmp,0}; q.push(x4);
        cin>>k;
        for (int i=1;i<=k;i++)
        {
            int x,y;
            cin>>x>>y;
            ft[x][y]=i;
        }
        int goal=(1<<k)-1;
        memset(ff,1,sizeof(ff));
        int ans=INF,xans,yans,zans,eans=goal;
        while (!q.empty())
        {
            re x=q.front(); q.pop();
            if (dp[x.a][x.b][x.c][x.d]>ans) continue;
            for (int i=1;i<=4;i++)
              if (pd(x,i))
              {
                  re r=js2(x,i);
                  if (dp[x.a][x.b][x.c][x.d]+abs(w[x.a+dx[i]][x.b+dy[i]]-w[x.a][x.b])+1<dp[x.a+dx[i]][x.b+dy[i]][r.a][r.b]||dp[x.a+dx[i]][x.b+dy[i]][r.a][r.b]==-1)
                  {
                      pre2[1][x.a+dx[i]][x.b+dy[i]][r.a][r.b]=(i-1)>>1;
                      pre2[2][x.a+dx[i]][x.b+dy[i]][r.a][r.b]=(i-1)&1;
                      pre[x.a+dx[i]][x.b+dy[i]][r.a][r.b]=x.c;
                      dp[x.a+dx[i]][x.b+dy[i]][r.a][r.b]=
                      dp[x.a][x.b][x.c][x.d]+abs(w[x.a+dx[i]][x.b+dy[i]]-w[x.a][x.b])+1;
                      re tmp=re{x.a+dx[i],x.b+dy[i],r.a,r.b};
                      if (r.b!=goal&&ff[x.a+dx[i]][x.b+dy[i]][r.a][r.b])
                      {
                      q.push(tmp); ff[x.a+dx[i]][x.b+dy[i]][r.a][r.b]=0;
                    }
                    if (r.b==goal&&dp[x.a+dx[i]][x.b+dy[i]][r.a][r.b]<ans)
                    {
                        ans=dp[x.a+dx[i]][x.b+dy[i]][r.a][r.b];
                        xans=x.a+dx[i]; yans=x.b+dy[i]; zans=r.a;
                    }
                }
              }
            ff[x.a][x.b][x.c][x.d]=1;
        }
        int cnt=0;
        if (ans==INF) cout<<"No solution.";
        else
        {
          cout<<ans<<endl;
          while (pre[xans][yans][zans][eans]!=-1)
          {
              int x=pre2[1][xans][yans][zans][eans]*2+pre2[2][xans][yans][zans][eans];
              jl[++cnt]=x;
              zans=pre[xans][yans][zans][eans];
              if (ft[xans][yans]) eans^=1<<(ft[xans][yans]-1);
              if (x==0) xans--;
              if (x==1) xans++;
              if (x==2) yans--;
              if (x==3) yans++;
          }
          for (int i=cnt;i;i--)
          { 
            if (jl[i]==0) cout<<'D';
            if (jl[i]==1) cout<<'U';
            if (jl[i]==2) cout<<'R';
            if (jl[i]==3) cout<<'L';
          }
        }
        return 0;
    }
  • 相关阅读:
    OpenCV特征描述
    OpenCV特征点检测
    expect实现无交互操作
    文件的修改时间
    sshd登录攻击
    tcp三次握手和syn 洪水攻击
    vim使用
    PHP拓展开发
    【转】LINUX 手动建立SWAP文件及删除
    Ubuntu下crontab命令的用法
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8855369.html
Copyright © 2011-2022 走看看