zoukankan      html  css  js  c++  java
  • 工作区的颜值选择(简单)

    https://nanti.jisuanke.com/t/A1012

    计蒜课上的练习题,只说简单版本的做法。

    最大数据为61个k的值,2*3=6个位置,枚举法共用61^(指数)6=大约500亿,在百亿级别,且可以对其用当前sum>ans(最小值)时回溯剪枝,大大降低运算量。

    给的时间是5000ms,所以可以接收几十亿或者百亿级别的数据。重新测速之后发现我的电脑10亿for循环大概两秒,但是本题k=30时测到的运行时间是大概几百ms到2000不等,证明剪枝确确实实的减少了非常多的运算,至少降低到了10亿以下。想想解答树的关系也可想而知,第n层数量有2k^n种可能。当k=30的时候,下一层单一层结点的数量就是上边所有结点数量和的60倍(其实也就是上一层的60倍,再往上的结点根本少到不够加),所以!剪枝非常有必要!!!

    采用DFS深度优先搜索进行遍历。

    先发自己的错误代码:

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #define maxn 5
    #define rep(i,n,t) for(int i=(n);i<(t);i++)
    #define mms(a,b) memset(a,(b),sizeof(a))
    int fs[maxn][maxn]; int wf[maxn][maxn];int ks[maxn][maxn];
    
    int n, m, k; int ans;
    using namespace std;
    
    bool cheak(int i, int j)
    {
        if (i < n&&i>=0 && j < m&&j>=0) return true;
        return false;
    }
    
    void DFS(int i,int j,int sum )
    {
        if (i == n) { ans = min(ans, sum); return; };
        if (i >= n && i < 0 && j < 0 && j >= m) return;
        rep(l, -k, k + 1) {
            ks[i][j] = l; cout << &sum<<endl;
            sum += (abs(l + i + 1 + j + 1) ^ fs[i][j])*wf[i][j];
            
            if (cheak(i - 1,j)) sum += abs(ks[i - 1][j] + ks[i][j]);
            if (cheak(i , j-1)) sum += abs(ks[i][j-1] + ks[i][j]);
            cout << sum << endl;
            if(j<m-1)DFS(i, j + 1, sum);
            else DFS(i + 1, 0, sum);
        }
        
    }
    
    int main()
    {
        cin >> n >> m >> k;
        rep(i, 0, n) rep(j, 0, m) cin >> fs[i][j];
        rep(i, 0, n) rep(j, 0, m) cin >> wf[i][j];
        rep(i, 0, n) rep(j, 0, m) ans += abs((i + 1 + j + 1) ^ fs[i][j])*wf[i][j];
        DFS(0, 0, 0);
        cout << ans;
       return 0; }
    //为什么不对:在DFS递归中每次进行sum数值的更新,想法是每一层有当前自己的sum,与ans比较后回溯到上一层时, //sum会读到上一层的sum值,然后继续带入下一个k进行下一轮调用。结果在更新时出现了问题,忘了考虑每次都会进行数值更新 //而我所学习的博客博主做法是用一个函数(传值)来处理sum数值的更新,返回值也是传值返回计算结果,并用这个返回值作为 //调用下一层循环的参数。这样导致每层中的sum只是用作存储本层时的sum状态,不做运算。避免了我乱七八糟的问题。 //

    ac代码

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #define maxn 5
    #define rep(i,n,t) for(int i=(n);i<(t);i++)
    #define mms(a,b) memset(a,(b),sizeof(a))
    int fs[maxn][maxn]; int wf[maxn][maxn]; int ks[maxn][maxn];
    
    int n, m, k; int ans;
    using namespace std;
    
    bool cheak(int i, int j)
    {
        if (i < n&&i >= 0 && j < m&&j >= 0) return true;
        return false;
    }
    
    int updata(int i, int j, int sum)//sum的更新应于当前层数递归参数更新之后,并且下一层递归调用之前
    {
        sum += (abs(ks[i][j] + i + 1 + j + 1) ^ fs[i][j])*wf[i][j];
        if (cheak(i - 1, j)) sum += abs(ks[i - 1][j] + ks[i][j]);
        if (cheak(i, j - 1)) sum += abs(ks[i][j - 1] + ks[i][j]);
        return sum;
    }
    
    int DFS(int i, int j, int sum)//DFS写成int型
    {
        if (sum >= ans) return 0;//剪枝
        if (i == n) { ans = min(ans, sum); return 0; };
        rep(l, -k, k + 1) {
            ks[i][j] = l; 
            if (j<m-1)DFS(i, j + 1, updata(i,j,sum));//0~倒数第二个元素的脚标。
            else if(j==m-1)DFS(i + 1, 0, updata(i,j,sum));//当走到行末的时候应该调用下一行行首
        }
    
    }
    
    int main()
    {
        cin >> n >> m >> k;
        rep(i, 0, n) rep(j, 0, m) cin >> fs[i][j];
        rep(i, 0, n) rep(j, 0, m) cin >> wf[i][j];
        rep(i, 0, n) rep(j, 0, m) ans += abs((i + 1 + j + 1) ^ fs[i][j])*wf[i][j];
        DFS(0, 0, 0);
        cout << ans;
      return 0; }

    总结:

    简单模式下一道水题。DFS和BFS我是会了忘又忘了会,感觉原因是因为只记住了它的行为模式,代码还是打的少。

    要多打代码,把各种情况分类,以模板化的方式来针对不同的DFS和BFS情况来写才是王道,这样效率才高,当然理解算法的行为是前提。

    比如这道题就是一个“无标记,求最优型”(我瞎起的)。就要套用这种函数作为数据更新处理,参数只做当前递归层状态的递归模式。

    接下来几天我准备仔细的重新学一遍DFS和BFS再做相应练习来归纳总结。再开一篇来作为分类和模板。争取把以后遇到的都收集起来归归类。

    十分感谢这位大佬规范的代码,从中学到了好多好多!!!!!https://blog.csdn.net/mengzhengnan/article/details/46958273

    十分感谢这位大佬规范的代码,从中学到了好多好多!!!!!https://blog.csdn.net/mengzhengnan/article/details/46958273

    十分感谢这位大佬规范的代码,从中学到了好多好多!!!!!https://blog.csdn.net/mengzhengnan/article/details/46958273

  • 相关阅读:
    RPA-UiPath视频教程2
    skywalking链路监控
    RPA-UiPath视频教程1
    Redis基础与性能调优
    tomcat调优
    DDos、CC攻击与防御
    UiPath官方视频Level2
    UiPath直播课程
    UiPath手把手教程
    【0】python核心编程,第二章
  • 原文地址:https://www.cnblogs.com/worldcreator-zh/p/10508142.html
Copyright © 2011-2022 走看看