• CODEVS1358【DFS/状压DP】


    题目链接【http://codevs.cn/problem/1358/】

    题意:这个游戏在一个有10*10个格子的棋盘上进行,初始时棋子位于左上角,终点为右下角,棋盘上每个格子内有一个0到9的数字,每次棋子可以往右方或下方的相邻格子移动,求一条经过数字之和最小且经过0到9的所有数字的合法路径,输出其长度。(经过的数字包括左上角和右下角)。

    思路一:深搜(DFS),因为他只可以向左走或又走,那么每次有两个方向,走到终点的时候,最多走了20步,所以深度最深为20,可解。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int inf = 1e9 + 10;
    using namespace std;
    int a[15][15];
    int ans = inf;
    void DFS(int x, int y, int k, int sum)
    {
        if(x < 1 || x > 10 || y < 1 || y > 10) return ;
        k |=(1 << a[x][y]);
        sum += a[x][y];
        if(x == 10 && y == 10  && k == 1023)
            ans = min(ans, sum);
        DFS(x + 1, y, k, sum);
        DFS(x, y + 1, k, sum);
    }
    int main ()
    {
        for(int i = 1; i <= 10; i++)
            for(int j = 1; j <= 10; j++)
                scanf("%d", &a[i][j]);
        DFS(1, 1, 0, 0);
        printf("%d
    ", ans);
    }

    思路二:状压DP,dp[i][j][s],表示,要走(i,j)这个格子,s[0,(1<<10)-1],如果s中的第i位为1,表示到达dp[i][j][s]这个状态的时候数字i已经被访问过了,如果为0那么表示数字i没有被访问过,最后输出dp[10][10][(1<<10)-1];

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int inf = 1e9 + 10;
    using namespace std;
    int a[15][15];
    int dp[15][15][1 << 10];
    int main ()
    {
        for(int i = 1; i <= 10; i++)
            for(int j = 1; j <= 10; j++)
                scanf("%d", &a[i][j]);
        memset(dp,0x3f3f3f,sizeof(dp));
        for(int i = 1; i <= 10; i++)
            for(int j = 1; j <= 10; j++)
            {
                if(i == 1 && j == 1)
                {
                    dp[i][j][1 << a[i][j]] = a[i][j];
                    continue;
                }
                for(int k = 1; k < (1 << 10); k++)
                {
                    if(k & (1 << a[i][j]))
                    {
                        if(i > 1)
                            dp[i][j][k] = a[i][j] + min(dp[i - 1][j][k - (1 << a[i][j])], dp[i - 1][j][k]);
                        if(j > 1)
                            dp[i][j][k] = min(dp[i][j][k], a[i][j] + min(dp[i][j - 1][k - (1 << a[i][j])], dp[i][j - 1][k]));
                    }
                }
            }
        printf("%d
    ", dp[10][10][(1 << 10) - 1]);
    }
    想的太多,做的太少。
  • 相关阅读:
    注册算法入门
    call传参之通过堆栈
    winhex注意
    输入字符串长度
    integer promotion
    网页flash兼容浏览器代码
    逆向工程——注册篇
    esp定律的一点说明
    base64
    意外
  • 原文地址:https://www.cnblogs.com/pealicx/p/6429594.html
Copyright © 2020-2023  润新知