• P3956棋盘


    传送

    这看起来有点像个搜索,那我们就用搜索试试。

    dfs?bfs?

    其实都可以,但是窝只会dfs.。

    既然这里要用dfs,那么就要把每次搜到(m,m)时,使用的金币数量进行比较,取最小值。

    在搜索过程中肯定会遇到很多不是最优解的情况。既然不是最优解,那么我们可以用某些方式在搜索过程中就把这些情况给剪掉。(也就是剪枝)我们不妨再开一个二维数组best,best[i][j]表示走到点(i,j)所用的最少金币数量。这样搜索到点(i,j)时,如果当前花费的金币总数不小于best[i][j],那么就算这种情况能够到达终点,它也一定不是最优解,所以我们直接返回,不再搜索。这样就可以节省很多的时间(至少不会TLE)

    再考虑一些细节

    这里我们就不判断每个点是否到过了,因为在上面的剪枝中,第二次到达一个搜索过的点,花费的金币肯定不比第一次到达时花费的少。

    在搜索时,我们只搜索有颜色的点。对于那些可以使用魔法的无色格子,我们就直接把它设成有颜色的,并且标记已经使用过魔法。在回溯的时候再使它的颜色变为无色就好。

    这里红色是0,黄色是1,而那些没有颜色的点的初始值也是0。所以我们在输入颜色的时候,将有颜色的点的颜色+1,就可以区分了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int m,n,ma[109][109],be[109][109];//be就是best,ma就是map(地图)
    int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
    int read()//快读
    {
        char ch=getchar();
        int x=0;bool f=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=(x<<3)+(x<<1)+(ch^48);
            ch=getchar();
        }
        f?x=-x:x=x;
        return x;
    }
    void dfs(int nowx,int nowy,int cost,bool magic)
    {
        if(nowx==m&&nowy==m)
        {
            be[m][m]=min(be[m][m],cost);
            return ;
        }
        if(cost>=be[nowx][nowy])return ;
        be[nowx][nowy]=cost;
        for(int i=0;i<=3;i++)
        {
            int ex=nowx+dx[i],ey=nowy+dy[i];
            if(ex>=1&&ex<=m&&ey>=1&&ey<=m)
            {
                if(ma[ex][ey]!=0)//只搜索有颜色的点(无色可以覆盖成有色)
                {
                    if(ma[ex][ey]==ma[nowx][nowy])
                      dfs(ex,ey,cost,0);
                    else dfs(ex,ey,cost+1,0);  
                }
                else if(magic==0)//对于无色的点,看是否能使用魔法
                 {
                   ma[ex][ey]=ma[nowx][nowy];
                   dfs(ex,ey,cost+2,1);
                   ma[ex][ey]=0;//一定要记得回溯啊
                 }
                  
            }
        }
    }
    int main()
    {
        m=read();n=read();
        for(int i=1;i<=n;i++)
        {
            int x=read(),y=read(),c=read();
            c++;
            ma[x][y]=c;
        }
        memset(be,63,sizeof(be));
        dfs(1,1,0,0);
        if(be[m][m]<1061109567)//memset之后be的值是1061109567
          printf("%d
    ",be[m][m]);//be[m][m]就是最后的解
        else printf("-1");
        return 0;
    }
  • 相关阅读:
    动态内存Treap
    最大流Dinic
    图的遍历
    Aho_Corasick自动机(AC自动机)
    邻接表
    COJ 3007 Mr.Yang的小助手
    COJ 0601&0602 动态规划(二)及加强
    Codeforces 603A Alternative Thinking
    HDU 2222 Keywords Search
    codeforce--600D
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/11116126.html
Copyright © 2020-2023  润新知