517-coding #1 枚举算法
Posted ljc20020730
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了517-coding #1 枚举算法相关的知识,希望对你有一定的参考价值。
枚举的技巧(什么是枚举)
暴力? 模拟? for? dfs? bfs? ...
巧妙的枚举。(优化时间复杂度、统计区间的贡献)
... 暴力大家都会 ... 优化暴力... 变成正解。
About DFS/BFS
二进制状态压缩表示。
折办搜索然后匹配累加贡献。
A* IDA* 搜索
迭代加深的DFS...
About 序列上的枚举
若答案具有单调性可考虑枚举一个端点,二分右端点,加上整一段对答案的贡献。
若答案具有单调性可考虑双指针,加上整一段对答案的贡献。
...
Some Qestions
Problem A
给你一个4*4的黑白棋盘,每次可以将一个棋子反转颜色,同时这个棋子的上下左右都会反转,
问你最少反转几次,可以将整个棋盘变成同色的
Sol :显然不同格子最多只能被翻转一次(如果翻转两次那么必然会重复)
所以最多是需要$2^4 \times 4$的翻转状态。
直接枚举每一种点击可能,这时候状态压缩处理即可。
#include<iostream> #include<stdio.h> #include<string.h> #include<vector> #include<algorithm> using namespace std; char board[4][4]; int tot=17; char new_b[4][4]; static int dir[5][2]=1,0,-1,0,0,0,0,1,0,-1; bool check() for(int i=0;i<4;i++) for(int j=0;j<4;j++) if(new_b[i][j]!=new_b[0][0]) return false; return true; int main() int tT; cin>>tT; while(tT--) tot=17; for(int i=0;i<4;i++) for(int j=0;j<4;j++) cin>>board[i][j]; // for(int i=0;i<(1<<16);i++) for(int a=0;a<4;a++) for(int b=0;b<4;b++) new_b[a][b]=board[a][b]; int t=0; for(int j=0;j<16;j++) if(((1<<j)&i)) t++; int x=j/4,y=j%4; for(int k=0;k<5;k++) int xx=x+dir[k][0]; int yy=y+dir[k][1]; if(xx<0 || yy<0 || xx>=4 || yy>=4) continue; new_b[xx][yy]=new_b[xx][yy]==‘w‘?‘b‘:‘w‘; if(check()) tot=min(tot,t); if(tot<17) cout<<tot<<endl;; else cout<<"Impossible"<<endl;; if(tT != 0) puts(""); return 0;
Problem B
给你n S,以及n个数,求最短的连续子序列的长度使得这个连续子序列的和大于等于S
对于100%的数据 $1 \leq n\leq 10^5$
Problem C
给出一个数列$a_n$ 求有多少区间的xor之和等于区间的数的和
对于100%的数据 $1 \leq n \leq 10^5$
Sol :
以上是关于517-coding #1 枚举算法的主要内容,如果未能解决你的问题,请参考以下文章