栈栈 - DFS
1. HDOJ4699: 对顶栈(@对顶堆)的使用:对不起没看清题目是我菜鸡。。。原文为"multiple test cases."所以才会while(scanf()!=EOF)之类
//在这里遇到了传说中的scanf字符缓冲问题,,,哭了 //然后“https://bbs.csdn.net/topics/70106056”中有个大佬说使用空格可以保证输入流中过滤空格、TAB、\n这三中字符 //原因见“https://wenwen.sogou.com/z/q656588149.htm” //另外有个题解是添加了如下while代码块解决的问题,原因暂。。。求教张雷??orz while (opc<'A' || opc>'Z') { scanf("%c", &opc); cout << "opc:" << opc << '?'; }
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <queue> 9 #include <stack> 10 #include <cmath> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long ll; 15 #define MS(x) memset(x,0,sizeof(x)); 16 #define inf 0x3f3f3f3f 17 18 const int maxn = 2000000; 19 int prefix[maxn]; 20 21 int main() 22 { 23 char ch; 24 int n; 25 while (scanf("%d", &n) != EOF) //对不起没看清题目是我菜鸡。。。原文为"multiple test cases." 26 { 27 stack <int> sLeft; 28 stack <int> sRight; 29 int sum = 0, x; 30 prefix[0] = -999999999; 31 while (n--) 32 { 33 scanf(" %c", &ch); 34 if (ch == 'I') 35 { 36 scanf("%d", &x); 37 sLeft.push(x); 38 sum += x; 39 prefix[sLeft.size()] = max(sum, prefix[sLeft.size() - 1]); 40 } 41 else if (ch == 'D' && sLeft.size() >= 1) 42 { 43 sum -= sLeft.top(); 44 sLeft.pop(); 45 } 46 else if (ch == 'L' && sLeft.size() >= 1) 47 { 48 sum -= sLeft.top(); 49 sRight.push(sLeft.top()); 50 sLeft.pop(); 51 } 52 else if (ch == 'R' && sRight.size() >= 1) 53 { 54 sLeft.push(sRight.top()); 55 sum += sRight.top(); 56 prefix[sLeft.size()] = max(sum, prefix[sLeft.size() - 1]); 57 sRight.pop(); 58 } 59 else if (ch == 'Q') 60 { 61 scanf("%d", &x); 62 printf("%d\n", prefix[x]); 63 } 64 } 65 } 66 return 0; 67 }
单调栈算法——借助单调性,及时排除不可能的选项,保持策略集合的高度有效性和秩序性,可用于解决最大连续矩形面积问题
Solve
这其实是一道单调栈模板题。先思考一个问题,如果题目中的矩形的高度都是单调递增的,如何得到最优解?显然有一个贪心的策略,就是以每一个矩形的高度作为最终大矩形的高度,看最宽能是多少,然后统计最优解。
但如果进来的下一矩形比上一个低,它其实相当于限制了之前矩形的高度,那么之前矩形比这个矩形高出的高度在以后的统计中就没有丝毫用处了,如果我们在这个时候把以之前矩形的高度作为最终高度的答案统计掉,那么反正以后的统计和上一个矩形没有关系,还不如把他删除。
这样,我们实际上就得到了单调栈的模型,只需要维护一个单调栈,在维护单调性的弹出操作时统计宽度,更新答案即可在O(n) O(n)O(n)实际内得到最优解。
为了方便把最后剩下的,以及单调递增的矩形也统计进去,我们假设a[n+1]的位置有一个高度为0的矩形,最后将它加入单调栈时他会将所有矩形都弹出,那么答案也就完成最后的更新了(转)。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <queue> 9 #include <stack> 10 #include <cmath> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long ll; 15 #define MS(x) memset(x,0,sizeof(x)); 16 #define inf 0x3f3f3f3f 17 18 const int maxn = 100005; 19 stack<pair<int, int> > hw; // height + width 20 int a[maxn]; 21 22 int main() 23 { 24 int n; 25 while (scanf("%d", &n) && n != 0) 26 { 27 MS(a); 28 ll ans = 0; //记住一定要初始化为0,(其他的包括数组重复利用的都要!)不然就卡得你亲妈都不认识 29 for (int i = 1; i <= n; i++) 30 { 31 scanf("%d", &a[i]); 32 } 33 a[n + 1] = 0; 34 for (int i = 1; i <= n + 1; i++) 35 { 36 int width = 0; 37 while (hw.size() >= 1 && a[i] <= hw.top().first) 38 { 39 width += hw.top().second; 40 ans = max(ans, (ll)hw.top().first * width); 41 hw.pop(); 42 } 43 hw.push(make_pair(a[i], width + 1)); 44 } 45 printf("%lld\n", ans); 46 } 47 return 0; 48 }
3. 洛谷P4147: 单调栈 / 悬线法 / 并查集——最大子矩阵(相当于POJ3494加了一层字符糖衣)
Solve
这个用单调栈是有奇效的,预处理一番就好,开始笨脑壳预处理后还不知道怎么用单调栈(实际上就是个二维(趴))
悬线法和并查集工业等以后学到再贴别的地方附个链接吧~
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <queue> 9 #include <stack> 10 #include <cmath> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long ll; 15 #define MS(x) memset(x,0,sizeof(x)); 16 #define inf 0x3f3f3f3f 17 18 const int maxn = 1005; 19 20 stack<pair<int, int> > sizer;//h+w 21 char tmap[maxn][maxn]; 22 int init[maxn][maxn]; 23 24 int main() 25 { 26 //input 27 int N, M; 28 scanf("%d %d", &N, &M); 29 MS(init); 30 for (int i = 1; i <= N; i++) 31 for (int j = 1; j <= M; j++) 32 scanf(" %c", &tmap[i][j]); 33 //init 34 for (size_t i = 1; i <= M; i++) 35 if (tmap[1][i] == 'F') 36 init[1][i] = 1; 37 init[1][M + 1] = 0;//同下 38 for (int i = 2; i <= N; i++) 39 for (int j = 1; j <= M; j++) 40 { 41 init[i][M + 1] = 0;//之所以要在后面多加一个高度0是为了在最后能把单调栈所有剩余元素弹出计算最后一个大矩阵 42 if (tmap[i][j] == 'F') 43 tmap[i - 1][j] == 'F' ? init[i][j] = init[i - 1][j] + 1 : init[i][j] = 1; 44 } 45 //show the init rectangle 46 //for (int i = 1; i <= N; i++) 47 //{ 48 // for (int j = 1; j <= M; j++) 49 // printf("%d ", init[i][j]); 50 // puts(""); 51 //} 52 53 //monotonous stack 54 ll ans = 0; 55 for (int i = 1; i <= N; i++) 56 { 57 for (int j = 1; j <= M + 1; j++) //notice there need +1 too 58 { 59 int width = 0; 60 while (sizer.size() >= 1 && sizer.top().first >= init[i][j]) 61 { 62 width += sizer.top().second; 63 ans = max(ans, (ll)sizer.top().first * width); 64 sizer.pop(); 65 } 66 sizer.push(make_pair(init[i][j], width + 1)); //托到这里再一起加1,如果初始化width=1的话,在while里的累加就会多带一个1 67 } 68 sizer.pop(); //each line clear the monotonous stack 69 } 70 printf("%lld", ans * 3); 71 return 0; 72 }
6. CodeForce 1104 Game with string/洛谷CF1104B:其实就是个破水题谁用dfs谁瘪犊子
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
DFS(Depth-First-Search)
递归实现(较易):从初始状态开始,递归一直往深处走,直到找到解或者走不下去了为止。
dfs(depth): if(find the solve || out the index || can't move) return; def(depth+1);
栈实现:一般比递归麻烦,但递归本质上还是栈(调用系统栈)
init(stack); stack.push(point); while(!stack.empty()): x = stack.top(); if(x has a approximal point that not be visited): stack.push(approximal point); continue; end if stack.empty();
4. HDU1241: DFS(栈实现 / 递归实现) 【你们大一训练的例题啊亲】🙈
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #define inf 0X7f7f7f7f 10 #define MS_I(x) memset(x,-inf,sizeof(x)) 11 #define MS(x) memset(x,0,sizeof(x)) 12 #define MSI(x) memset(x,inf,sizeof(x)) 13 using namespace std; 14 typedef long long ll; 15 typedef unsigned long long ull; 16 const int maxn = 1e6 + 5; 17 using namespace std; 18 19 int oil[105][105]; 20 bool visit[105][105]; 21 int n, m; 22 23 void dfs(int x, int y) 24 { 25 //越界+已标记+死胡同 26 //x代表行,y代表列(不要当作Pos(x,y),要的话要记得反过来) 27 if (visit[x][y] || oil[x][y] == '*' || x <= 0 || y <= 0 || x > n || y > m) 28 return; 29 visit[x][y] = true; 30 dfs(x + 1, y + 1); 31 dfs(x + 1, y); 32 dfs(x + 1, y - 1); 33 dfs(x, y - 1); 34 dfs(x, y + 1); 35 dfs(x - 1, y - 1); 36 dfs(x - 1, y); 37 dfs(x - 1, y + 1); 38 } 39 40 int main() 41 { 42 while (scanf("%d %d", &n, &m) && m != 0) 43 { 44 MS(oil); 45 MS(visit); 46 for (int i = 1; i <= n; i++) 47 for (int j = 1; j <= m; j++) 48 scanf(" %c", &oil[i][j]);//%c前加空格屏蔽空白字符 49 50 int cnt = 0; 51 for (int i = 1; i <= n; i++) 52 for (int j = 1; j <= m; j++) 53 if (oil[i][j] == '@' && !visit[i][j]) 54 { 55 dfs(i, j); 56 cnt++; 57 } 58 printf("%d\n", cnt); 59 } 60 return 0; 61 }
5. CodeForce 377A Maze:从递归最深处填'X'
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #include <stack> 10 #include <queue> 11 #define inf 0X7f7f7f7f 12 #define MS_I(x) memset(x,-inf,sizeof(x)) 13 #define MS(x) memset(x,0,sizeof(x)) 14 #define MSI(x) memset(x,inf,sizeof(x)) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 1e5 + 5; 19 using namespace std; 20 21 char matrix[505][505]; 22 bool visit[505][505]; 23 24 int n, m, k; 25 26 void dfs(int x, int y) 27 { 28 if (x < 0 || y < 0 || x >= n || y >= m || visit[x][y] || matrix[x][y] == '#') 29 return; 30 visit[x][y] = true; 31 dfs(x + 1, y); 32 dfs(x - 1, y); 33 dfs(x, y + 1); 34 dfs(x, y - 1); 35 if (k)//这个地方是深搜遍历的断头(递归结构还得好好熟练掌握🙈) 36 { 37 k--; 38 matrix[x][y] = 'X'; 39 } 40 } 41 42 int main() 43 { 44 scanf("%d %d %d", &n, &m, &k); 45 for (int i = 0; i < n; i++) 46 for (int j = 0; j < m; j++) 47 scanf(" %c", &matrix[i][j]); 48 for (int i = 0; i < n; i++) 49 for (int j = 0; j < m; j++) 50 dfs(i, j); 51 for (int i = 0; i < n; i++) 52 { 53 for (int j = 0; j < m; j++) 54 printf("%c", matrix[i][j]); 55 puts(""); 56 } 57 58 return 0; 59 }
6. 洛谷P1219 八皇后:
Ⅰ按行作为层数,做到按字典序输出
Ⅱ每到层数为n,说明递归到头有解,ans++
Ⅲ最关键的是,要记得在循环里dfs前后要将数组重新初始化
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #include <stack> 10 #include <queue> 11 #define inf 0X7f7f7f7f 12 #define MS_I(x) memset(x,-inf,sizeof(x)) 13 #define MS(x) memset(x,0,sizeof(x)) 14 #define MSI(x) memset(x,inf,sizeof(x)) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 1e5 + 5; 19 using namespace std; 20 21 bool column[15], lh[30], rh[30];//lh:x-y; rh:x+y 22 int row[15]; 23 24 int n, ans = 0; 25 26 void dfs(int x, int y) 27 { 28 if (column[y] || lh[x - y + 15] || rh[x + y] || x > n) 29 return; 30 row[x] = y; 31 if (x == n) 32 { 33 ans++; 34 if (ans <= 3) 35 { 36 for (int i = 1; i <= n; i++) 37 printf("%d ", row[i]); 38 puts(""); 39 } 40 } 41 for (int i = 1; i <= n; i++) 42 { 43 column[y] = lh[x - y + 15] = rh[x + y] = 1; 44 dfs(x + 1, i); 45 column[y] = lh[x - y + 15] = rh[x + y] = 0; 46 } 47 } 48 49 int main() 50 { 51 scanf("%d", &n); 52 for (int y = 1; y <= n; y++) 53 { 54 MS(column); 55 MS(lh); 56 MS(rh); 57 MS(row); 58 dfs(1, y); 59 } 60 printf("%d", ans); 61 return 0; 62 }
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #include <stack> 10 #include <queue> 11 #define inf 0X7f7f7f7f 12 #define MS_I(x) memset(x,-inf,sizeof(x)) 13 #define MS(x) memset(x,0,sizeof(x)) 14 #define MSI(x) memset(x,inf,sizeof(x)) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 1e5 + 5; 19 using namespace std; 20 21 bool column[15], lh[30], rh[30];//lh:x-y; rh:x+y 22 int row[15]; 23 24 int n, ans = 0; 25 26 void dfs(int x)//x:row 27 { 28 if (x == n + 1) 29 { 30 ans++; 31 if (ans <= 3) 32 { 33 for (int i = 1; i <= n; i++) 34 printf("%d ", row[i]); 35 puts(""); 36 } 37 } 38 for (int y = 1; y <= n; y++)//y:column 39 { 40 if (column[y] || lh[x - y + 15] || rh[x + y] || x > n) 41 continue; 42 row[x] = y;//储存各row的column 43 column[y] = lh[x - y + 15] = rh[x + y] = 1; 44 dfs(x + 1); 45 column[y] = lh[x - y + 15] = rh[x + y] = 0;//还原 46 } 47 } 48 49 int main() 50 { 51 scanf("%d", &n); 52 dfs(1); 53 printf("%d", ans); 54 return 0; 55 }
7. 洛谷P1019 单词接龙:不是图一开始有点无措,都在注释里了,然后,string内的substr()🐂🍺哈哈
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #include <stack> 10 #include <queue> 11 #define inf 0X7f7f7f7f 12 #define MS_I(x) memset(x,-inf,sizeof(x)) 13 #define MS(x) memset(x,0,sizeof(x)) 14 #define MSI(x) memset(x,inf,sizeof(x)) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 1e5 + 5; 19 using namespace std; 20 21 int vistime[25]; 22 string str[25]; 23 24 int n, ans = 0; 25 26 void dfs(string now, int sum) 27 { 28 ans = max(ans, sum);//存储longest 29 for (int i = 1; i <= n; i++) 30 { 31 if (vistime[i] >= 2)//如果出现两次以上,跳过 32 continue; 33 int nxlen = 0; 34 for (int j = 1; j <= min(now.length(), str[i].length()); j++)//min防止越界 35 { 36 if (now.substr(now.length() - j) == str[i].substr(0, j))//得出最短重叠子串 37 { 38 nxlen = j; 39 break; 40 } 41 } 42 if (nxlen == 0)//如果now串与str[i]无重叠,跳过 43 continue; 44 vistime[i]++; 45 //这里之前我写成了sum += str[i].length() - nxlen);再将sum带入,然而sum作为全局变量肯定不能的🙈 46 dfs(str[i], sum + str[i].length() - nxlen);//我缓缓打出一个? 47 vistime[i]--;//you can get it 48 } 49 } 50 51 int main() 52 { 53 scanf("%d", &n); 54 for (int y = 1; y <= n; y++) 55 cin >> str[y]; 56 string c; 57 cin >> c; 58 dfs(c, 1); 59 printf("%d", ans); 60 return 0; 61 }
8. 洛谷P1101 单词方阵:明天(今天)还要七点去“打工”,他们打游戏睡不着干脆写了这道题= =,我tql
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #include <stack> 10 #include <queue> 11 #define inf 0X7f7f7f7f 12 #define MS_I(x) memset(x,-inf,sizeof(x)) 13 #define MS(x) memset(x,0,sizeof(x)) 14 #define MSI(x) memset(x,inf,sizeof(x)) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 1e5 + 5; 19 using namespace std; 20 21 bool visit[105][105]; 22 char matrix[105][105], matrix2[105][105]; 23 int dirx[8] = { 1,1,1,0,0,-1,-1,-1 }; 24 int diry[8] = { -1,1,0,1,-1,1,0,-1 }; 25 int n, ans = 0; 26 const char s[8] = "yizhong"; 27 28 void dfs(int x, int y, int k, int index) //k表示深搜方向(const) 29 { 30 if (index == 6) 31 for (int i = 0; i < 7; i++) 32 matrix2[x - i * dirx[k]][y - i * diry[k]] = s[6 - i]; 33 if (x <= 0 || x > n | y <= 0 || y > n || matrix[x][y] != s[index]) 34 return; 35 dfs(x + dirx[k], y + diry[k], k, index + 1); 36 } 37 38 int main() 39 { 40 scanf("%d", &n); 41 for (int i = 1; i <= n; i++) 42 for (int j = 1; j <= n; j++) 43 scanf(" %c", &matrix[i][j]); 44 45 //提前构造备份 46 for (int i = 1; i <= n; i++) 47 for (int j = 1; j <= n; j++) 48 matrix2[i][j] = '*'; 49 50 for (int i = 1; i <= n; i++) 51 for (int j = 1; j <= n; j++) 52 if (matrix[i][j] == 'y')//如果是'y'开头则分八个方向一直深搜 53 for (int k = 0; k < 8; k++) 54 dfs(i, j, k, 0); 55 56 for (int i = 1; i <= n; i++) 57 { 58 for (int j = 1; j <= n; j++) 59 printf("%c", matrix2[i][j]); 60 puts(""); 61 } 62 return 0; 63 }
9. 洛谷P1605 迷宫:依然是回溯加成的水题
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #include <stack> 10 #include <queue> 11 #define inf 0X7f7f7f7f 12 #define MS_I(x) memset(x,-inf,sizeof(x)) 13 #define MS(x) memset(x,0,sizeof(x)) 14 #define MSI(x) memset(x,inf,sizeof(x)) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 1e5 + 5; 19 using namespace std; 20 21 struct pos 22 { 23 int x; 24 int y; 25 }; 26 27 int n, m, t; 28 pos s, e; 29 bool obstacle[10][10], visit[10][10]; 30 int ans = 0; 31 int dirx[4] = { 1,-1,0,0 }; 32 int diry[4] = { 0,0,1,-1 }; 33 34 void dfs(int x, int y) 35 { 36 if (x > m || y > n || x <= 0 || y <= 0 || obstacle[x][y] || visit[x][y]) 37 return; 38 if ((x == e.x && y == e.y)) 39 { 40 ans++; 41 return; 42 } 43 visit[x][y] = true; 44 for (int i = 0; i < 4; i++)//visit要回溯🙈 45 dfs(x + dirx[i], y + diry[i]); 46 visit[x][y] = false; 47 } 48 49 int main() 50 { 51 scanf("%d %d %d", &n, &m, &t); 52 scanf("%d %d %d %d", &s.x, &s.y, &e.x, &e.y); 53 int x, y; 54 for (int i = 0; i < t; i++) 55 { 56 scanf("%d %d", &x, &y); 57 obstacle[x][y] = true; 58 } 59 dfs(s.x, s.y); 60 printf("%d\n", ans); 61 return 0; 62 }
10. 洛谷P1040 加分二叉树:“我下次一定自己做出dfs!”“真香!”
首先这个区间dp我就黑人问号了,上个星期才学的树,中序遍历前序遍历我今个儿算是记牢了
中序遍历12345变区间这么好用的吗???前序遍历就是一个printt解决了吗???
看着大佬的题解打完的,日后lz学了区间dp巩固了树一定回马杀你丫的!
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #define inf 0X7f7f7f7f 6 #define MS_I(x) memset(x,-inf,sizeof(x)) 7 #define MS(x) memset(x,0,sizeof(x)) 8 #define MSI(x) memset(x,inf,sizeof(x)) 9 using namespace std; 10 typedef long long ll; 11 typedef unsigned long long ull; 12 const int maxn = 1e5 + 5; 13 using namespace std; 14 15 int n; 16 int tree[32]; 17 int root[32][32]; 18 int val[32][32]; 19 20 int dfs(int l,int r)//进行dfs搜索,dfs(l,r)的值为l-r区间子树的加分值 21 { 22 if(l>r) 23 return 1;//如果l>r,说明子树为空,题目有说明若子树为空默认为1 24 if(l==r) 25 { 26 root[l][r]=l; 27 return tree[l]; 28 //若l=r,说明在叶子节点上,这种节点的根就是它自己。 29 } 30 if(val[l][r]) 31 return val[l][r]; 32 //这里是记忆化搜索的应用,即如果此区间的值已经被计算过,就不再用dfs(l,r)求其值,而使用val[][]数组中已经保存的值。 33 //因为val初始值是0,所以只要val不等于0即表示此区间已经被计算过 34 for(int i=l;i<=r;i++) 35 { 36 //这里是枚举根节点,从l-r,i为根节点编号。 37 int temp=dfs(l,i-1)*dfs(i+1,r)+tree[i]; 38 //计算当i为此节点编号时i子树的加分 39 //这三个分别对应: 40 //subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数。 41 if(temp>val[l][r]) 42 { 43 root[l][r]=i; 44 val[l][r]=temp; 45 } 46 //如果i为根节点的子树加分 大于 已有的区间的加分,则保存其根节点和加分。 47 } 48 return val[l][r]; 49 //返回 记忆化搜索 50 } 51 52 void print(int l,int r) 53 { 54 if(l>r) 55 return; 56 printf("%d ", root[l][r]); 57 print(l,root[l][r]-1); 58 print(root[l][r]+1,r); 59 } 60 61 int main() 62 { 63 scanf("%d", &n); 64 for (int i = 1; i <= n; i++) 65 scanf("%d", &tree[i]); 66 printf("%d\n", dfs(1, n)); 67 printt(1, n); 68 return 0; 69 }
11. 洛谷P1092 虫食算:
Code
12.数独
① POJ2676:
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #include <stack> 10 #include <queue> 11 #define inf 0X7f7f7f7f 12 #define MS_I(x) memset(x,-inf,sizeof(x)) 13 #define MS(x) memset(x,0,sizeof(x)) 14 #define MSI(x) memset(x,inf,sizeof(x)) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 1e5 + 5; 19 using namespace std; 20 21 int matrix[9][9]; 22 bool flag; 23 24 bool check(int x, int y, int num) 25 { 26 int xn = x / 3 * 3, yn = y / 3 * 3; 27 //cout << "x:" << x << "y:" << y << "i:" << i << endl; 28 for (int j = 0; j < 9; j++) 29 if (matrix[x][j] == num) 30 return false; 31 //cout << "x:" << x << "y:" << y << "i:" << i << endl; 32 for (int j = 0; j < 9; j++) 33 if (matrix[j][y] == num) 34 return false; 35 //cout << "x:" << x << "y:" << y << "i:" << i << endl; 36 for (int xi = xn; xi < xn + 3; xi++) 37 for (int yi = yn; yi < yn + 3; yi++) 38 if (matrix[xi][yi] == num) 39 return false; 40 //cout << "x:" << x << "y:" << y << "i:" << i << endl; 41 } 42 43 void dfs(int x, int y) 44 { 45 if (x < 0 || y >= 9 || y < 0) 46 return; 47 if (flag) 48 true; 49 if (x == 9) 50 { 51 flag = true; 52 return; 53 } 54 while (matrix[x][y])//跳过已有的 55 { 56 if (y == 8) 57 x++, y = 0; 58 else 59 y++; 60 if (x == 9) 61 { 62 flag = true; 63 return; 64 } 65 } 66 for (int i = 1; i <= 9; i++) 67 { 68 if (!check(x, y, i)) 69 continue; 70 matrix[x][y] = i; 71 if (y < 8) 72 dfs(x, y + 1); 73 else dfs(x + 1, 0); 74 if (flag) 75 return; 76 matrix[x][y] = 0; 77 } 78 } 79 80 int main() 81 { 82 int t; 83 scanf("%d", &t); 84 while (t--) 85 { 86 flag = false; 87 for (int i = 0; i < 9; i++) 88 for (int j = 0; j < 9; j++) 89 scanf("%1d", &matrix[i][j]);//这个输入格式还是🙈tql 90 dfs(0, 0); 91 for (int i = 0; i < 9; i++) 92 { 93 for (int j = 0; j < 9; j++) 94 printf("%d", matrix[i][j]); 95 puts(""); 96 } 97 } 98 return 0; 99 }
② POJ3074:注释都在代码里,二进制真的秀,AcWing视频讲解的小哥哥码代码的样子真的i了!
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #include <stack> 10 #include <queue> 11 #define inf 0X7f7f7f7f 12 #define MS_I(x) memset(x,-inf,sizeof(x)) 13 #define MS(x) memset(x,0,sizeof(x)) 14 #define MSI(x) memset(x,inf,sizeof(x)) 15 #define N 9 16 using namespace std; 17 typedef long long ll; 18 typedef unsigned long long ull; 19 const int maxn = 1e5 + 5; 20 using namespace std; 21 22 int ones[1 << N]; 23 int row[N]; 24 int column[N]; 25 int cell[3][3]; 26 bool flag; 27 int map[1 << N]; 28 string ms; 29 void init()//全为1(都可填)(再用二进制运算减去,贼方便) 30 { 31 for (int i = 0; i < N; i++) 32 { 33 row[i] = column[i] = (1 << N) - 1; 34 } 35 for (int i = 0; i < 3; i++) 36 { 37 for (int j = 0; j < 3; j++) 38 cell[i][j] = (1 << N) - 1; 39 } 40 } 41 inline int lowbit(int x)//10100 = 100 42 { 43 return x & (-x); 44 } 45 inline int get(int x, int y)//二进制交集 46 { 47 return row[x] & column[y] & cell[x / 3][y / 3]; 48 } 49 bool dfs(int num) 50 { 51 if (!num) 52 return true; 53 int minv = 10; 54 int x, y; 55 //全局查找可选数最少的 56 for (int i = 0; i < N; i++) 57 { 58 for (int j = 0; j < N; j++) 59 if (ms[i * 9 + j] == '.') 60 { 61 int t = ones[get(i, j)]; 62 if (t < minv) 63 { 64 minv = t; 65 x = i, y = j; 66 } 67 } 68 } 69 for (int i = get(x, y); i; i -= lowbit(i)) 70 { 71 int t = map[lowbit(i)]; 72 //更新 73 ms[x * 9 + y] = t + '1'; 74 row[x] -= 1 << t; 75 column[y] -= 1 << t; 76 cell[x / 3][y / 3] -= 1 << t; 77 if (dfs(num - 1))//下一级 78 return true; 79 //回溯 80 ms[x * 9 + y] = '.'; 81 row[x] += 1 << t; 82 column[y] += 1 << t; 83 cell[x / 3][y / 3] += 1 << t; 84 } 85 return false; 86 } 87 88 int main() 89 { 90 //map[100] = 2,map[1000] = 3 91 for (int i = 0; i < N; i++) 92 map[1 << i] = i; 93 //ones[10100] = 2 94 for (int i = 0; i < 1 << N; i++) 95 { 96 int s = 0; 97 for (int j = i; j; j -= lowbit(j)) 98 s++; 99 ones[i] = s; 100 } 101 102 while (true) 103 { 104 init(); 105 int cnt = 0;//有多少个需要填 106 flag = false; 107 cin >> ms; 108 if (ms[0] == 'e')//end退出 109 break; 110 for (int i = 0, k = 0; i < N; i++) 111 { 112 for (int j = 0; j < N; j++, k++) 113 { 114 if (ms[k] != '.') 115 { 116 int t = ms[k] - '1'; 117 row[i] -= 1 << t; 118 column[j] -= 1 << t; 119 cell[i / 3][j / 3] -= 1 << t; 120 } 121 else 122 cnt++; 123 } 124 } 125 //初始条件形成完毕 126 dfs(cnt); 127 cout << ms << endl; 128 } 129 return 0; 130 }
顺便学着用二进制做下之前的八皇后
二进制固定位数
小抄和lowbit也会了
怎么用其实才是痛点哈哈
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #include <stack> 10 #include <queue> 11 #define inf 0X7f7f7f7f 12 #define MS_I(x) memset(x,-inf,sizeof(x)) 13 #define MS(x) memset(x,0,sizeof(x)) 14 #define MSI(x) memset(x,inf,sizeof(x)) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 1e5 + 5; 19 using namespace std; 20 21 int row[14]; 22 int map[1 << 14]; 23 int column, lh, rh; 24 int n, ans = 0; 25 int layer = 0; 26 27 inline int lowbit(int x) 28 { 29 return x & -x; 30 } 31 //其实主要是思路吧 32 //一行为一层 33 //ll是这层左对角,rl是右对角,row是列 34 void dfs(int ll, int rl, int column) 35 { 36 if (column == (1 << n) - 1) 37 { 38 ans++; 39 if (ans <= 3) 40 { 41 for (int i = 0; i < n; i++) 42 printf("%d ", row[i]); 43 puts(""); 44 } 45 } 46 else 47 { 48 int pos = ((1 << n) - 1) & (~(ll | rl | column));//我觉得是固定位数 49 for (int i = pos; i; i -= lowbit(i)) 50 { 51 int cmp = lowbit(i); 52 row[layer++] = map[cmp]; 53 dfs((ll + cmp) << 1, (rl + cmp) >> 1, column + cmp); 54 row[layer--] = 0; 55 } 56 } 57 } 58 59 int main() 60 { 61 for (int i = 0; i < 14; i++)//小抄 62 map[1 << i] = i + 1; 63 scanf("%d", &n); 64 dfs(0, 0, 0); 65 printf("%d", ans); 66 return 0; 67 }
③ POJ3076:还是数独,16×16格(狗头)//没做出来。。。听说有DLX。。。我好难,以后补吧,之前的代码在这
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cmath> 9 #include <stack> 10 #include <queue> 11 #define inf 0X7f7f7f7f 12 #define MS_I(x) memset(x,-inf,sizeof(x)) 13 #define MS(x) memset(x,0,sizeof(x)) 14 #define MSI(x) memset(x,inf,sizeof(x)) 15 #define N 16 16 using namespace std; 17 typedef long long ll; 18 typedef unsigned long long ull; 19 const int maxn = 1e5 + 5; 20 using namespace std; 21 22 int row[N], column[N], cell[4][4]; 23 int map[1 << N]; 24 int ones[1 << N]; 25 char matrix[N][N]; 26 27 inline int lowbit(int x) 28 { 29 return x & -x; 30 } 31 inline int getpos(int x, int y) 32 { 33 return row[x] & column[y] & cell[x / 4][y / 4]; 34 } 35 void init() 36 { 37 for (int i = 0; i < N; i++) 38 { 39 row[i] = column[i] = (1 << N) - 1; 40 } 41 for (int i = 0; i < 4; i++) 42 { 43 for (int j = 0; j < 4; j++) 44 { 45 cell[i][j] = (1 << N) - 1; 46 } 47 } 48 } 49 bool dfs(int num) 50 { 51 if (!num) 52 return true; 53 //find the min 54 int minv = 17; 55 int x, y, pos; 56 for (int i = 0; i < N; i++) 57 { 58 for (int j = 0; j < N; j++) 59 { 60 if (matrix[i][j] == '-' && minv > ones[getpos(i, j)]) 61 { 62 minv = ones[getpos(i, j)]; 63 x = i, y = j; 64 } 65 } 66 } 67 pos = getpos(x, y); 68 for (int i = pos; i; i -= lowbit(i)) 69 { 70 int tnum = map[lowbit(i)]; 71 row[x] -= 1 << tnum; 72 column[y] -= 1 << tnum; 73 cell[x / 4][y / 4] -= 1 << tnum; 74 matrix[x][y] = tnum + 'A'; 75 if (dfs(num - 1)) 76 return true; 77 row[x] += 1 << tnum; 78 column[y] += 1 << tnum; 79 cell[x / 4][y / 4] += 1 << tnum; 80 matrix[x][y] = '-'; 81 } 82 return false; 83 } 84 85 int main() 86 { 87 int cnt = 0; 88 for (int i = 0; i < N; i++)//小抄 89 map[1 << i] = i; 90 for (int i = 0; i < (1 << N); i++) 91 { 92 int num = 0; 93 for (int j = i; j; j -= lowbit(j)) 94 { 95 num++; 96 } 97 ones[i] = num; 98 } 99 init(); 100 for (int i = 0; i < N; i++) 101 { 102 for (int j = 0; j < N; j++) 103 { 104 scanf(" %c", &matrix[i][j]); 105 if (matrix[i][j] != '-') 106 { 107 int tmp = matrix[i][j] - 'A'; 108 row[i] -= 1 << tmp; 109 column[j] -= 1 << tmp; 110 cell[i / 4][j / 4] -= 1 << tmp; 111 } 112 else 113 cnt++; 114 } 115 } 116 dfs(cnt); 117 for (int i = 0; i < N; i++) 118 { 119 for (int j = 0; j < N; j++) 120 printf("%c", matrix[i][j]); 121 puts(""); 122 } 123 return 0; 124 }
④ 洛谷P4573://我都不想做了哈哈哈哈,做bfs去,数独放放了啦(被16数独恶心到了嘿嘿)
事实是我还要接着把蓝书题做了的,move on~
13. POJ1011: