• [USACO3.3.3]camelot


      题目传送门:http://www.nocow.cn/index.php/Translate:USACO/camelot

      这道题让我心痛,一开始写写不出,后来拖了很久,决定去看题解,没想到又看不懂官方题解,唉!后来看了下面的题解做了出来。题解的话,大概就是先预处理每个格子到另外格子的位置,再枚举在王的坐标+-2位置接王,枚举所有棋子的集中点加起来计算就好了。我的代码为了方便略粗鲁。

      题解传送门:http://www.nocow.cn/index.php/USACO/camelot

      

    /*
    ID:abc31261
    LANG:C++
    TASK:camelot
    */
    
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<iostream>
    using namespace std;
    const int maxn=33,maxm=800;
    int n,m,ans=100000000,flag[maxn][maxn],f1[2][maxn][maxn][maxn][maxn],f[maxn][maxn],num=-1,numx[maxm],numy[maxm],knx[]={0,-2,-2,-1,-1,1,1,2,2},kny[]={0,-1,1,-2,2,-2,2,-1,1},
                                                    ky[]={0,-1,0,1,-1,1,-1,0,1},kx[]={0,-1,-1,-1,0,0,1,1,1};
    
    void read()
    {
        char in[5];
        scanf("%d%d",&n,&m);
        while (scanf("%s%d",in,&numx[++num])==2)numy[num]=in[0]-'A'+1;
        num--;
    }
    
    bool check(int x,int y)
    {
        if (x<=n && x>0 && y<=m && y>0)return true;
        return false;
    }
    
    void bfs(int a,int b,int c)
    {
        queue<int> qx,qy;
        qx.push(a),qy.push(b);
        memset(flag,true,sizeof(flag));
        flag[a][b]=false;
        f1[c][a][b][a][b]=0;
        while (!qx.empty())
        {
            int x=qx.front(),y=qy.front();qx.pop(),qy.pop();
            for (int i=1;i<=8;i++)
            {
                int x1=x+knx[i],y1=y+kny[i];
                if (c==1)x1=x+kx[i],y1=y+ky[i];
                if (check(x1,y1) && flag[x1][y1])
                { 
                    qx.push(x1),qy.push(y1);
                    flag[x1][y1]=false;
                    f1[c][a][b][x1][y1]=f1[c][a][b][x][y]+1;
                }
            }
        }
    }
    
    void solve()
    {
        int q,i,j,l,k;
        for (i=1;i<=n;i++)
            for (j=1;j<=m;j++)
            {
                f[i][j]+=f1[1][numx[0]][numy[0]][i][j];
                ans=min(ans,f[i][j]);
            }
        for (q=1;q<=num;q++)
            for (i=1;i<=n;i++)
                for (j=1;j<=m;j++)
                     for (l=numx[0]-2;l<=numx[0]+2;l++)
                         for (k=numy[0]-2;k<=numy[0]+2;k++)
                             if (l>0 && l<=n && k>0 && k<=m)
                               ans=min(f1[1][numx[0]][numy[0]][l][k]+f1[0][numx[q]][numy[q]][l][k]+f1[0][l][k][i][j]+f[i][j]-f1[0][numx[q]][numy[q]][i][j]-f1[1][numx[0]][numy[0]][i][j],ans);
        
    }
    int main()
    {
        int i,j,l;
        freopen("camelot.in","r",stdin);
        freopen("camelot.out","w",stdout);
        read();
        memset(f,0,sizeof(f));
        memset(f1,0x2f,sizeof(f1));
        bfs(numx[0],numy[0],1);
        for (i=1;i<=n;i++)
            for (j=1;j<=m;j++)bfs(i,j,0);
        for (i=1;i<=num;i++)
            for (j=1;j<=n;j++)
                for (l=1;l<=m;l++)
                f[j][l]+=f1[0][numx[i]][numy[i]][j][l];
        solve();
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    centos6.5下redis的安装与配置
    (函数分治法)实现pow函数(x的y次方幂)
    (数组)大数相乘,相加
    (树)根据排序数组或者排序链表重新构建BST树
    (合并 重叠数组)练习容器的用法
    (动态规划)最小分糖果问题
    (链表)链表的排序问题
    (链表)链表和加法的混合
    (函数)实现strstr函数
    (字符串动态规划)一个字符串变成另一个字符串的步骤数
  • 原文地址:https://www.cnblogs.com/Sun-Sea/p/5289831.html
Copyright © 2020-2023  润新知