工作区的颜值选择(简单)
Posted worldcreator-zh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工作区的颜值选择(简单)相关的知识,希望对你有一定的参考价值。
https://nanti.jisuanke.com/t/A1012
计蒜课上的练习题,只说简单版本的做法。
最大数据为61个k的值,2*3=6个位置,枚举法共用61^(指数)6=大约500亿,在百亿级别,且可以对其用当前sum>ans(最小值)时回溯剪枝,大大降低运算量。
给的时间是5000ms,所以可以接收几十亿或者百亿级别的数据。
采用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
以上是关于工作区的颜值选择(简单)的主要内容,如果未能解决你的问题,请参考以下文章
只会直接插入图片到PPT?图片这样处理,PPT的颜值瞬间提升几倍!
年轻人的颜值担当,当下正流行的开关面板设计,你pick哪一款?