文章目录
题目就不贴了,记录一下自己做题的思路和代码.
详细题目链接
1、迷宫(DFS)
解题思路:
DFS依次判断每一个点能否走出去。答案:31
代码
#include <iostream>
#include <cstring>
using namespace std;
const int N = 11;
int n = 10;
char g[N][N];
bool st[N][N];
int dx[4] = {
-1,0,1,0},dy[4] = {
0,1,0,-1};
int get(char c)
{
if(c == 'U') return 0;
else if(c == 'R') return 1;
else if(c == 'D') return 2;
else return 3;
}
bool dfs(int x,int y)
{
if(x <0 || x >= n || y < 0 || y >= n) return true;
st[x][y] = true;
int d = get(g[x][y]);
int a = x + dx[d], b = y + dy[d];
if(st[a][b]) return false;
if(dfs(a,b)) return true;
}
int main()
{
for(int i =0; i < n ;i ++ ) cin >> g[i];
int cnt = 0;
for(int i =0 ;i < n;i ++ )
for(int j = 0;j < n ; j ++ )
{
memset(st,0,sizeof st);
if(dfs(i,j)) cnt ++;
}
cout << cnt << endl;
}
// 答案:31
2、跳蚱蜢(BFS)
解题思路:
答案:20
代码
#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
int get_0(string &s)
{
for(int i = 0; i < s.size();i ++ )
if(s[i] == '0') return i;
}
int bfs()
{
string start = "012345678";
string end = "087654321";
unordered_map<string,int> step;
int d[4] = {
1,2,-1,-2};
step[start] = 0;
queue<string> q;
q.push(start);
while(q.size())
{
string s = q.front();
q.pop();
int cnt = step[s];
if(s == end) return cnt;
int pos = get_0(s);
for(int i = 0;i < 4;i ++)
{
swap(s[pos],s[((pos + d[i]) % 9 + 9) % 9 ]) ;// C ++ 取模
if(step.count(s) == 0)
{
step[s] = cnt + 1;
q.push(s);
}
swap(s[pos],s[((pos + d[i]) % 9 + 9) % 9 ]) ;// 交换回来
}
}
}
int main()
{
cout << bfs() << endl;
return 0;
}
3、魔方状态(BFS,不会)
解题思路
4、方格分割(DFS,不会)
解题思路
5,6代码填空题(略)
7、正则问题(DFS)
解题思路
递归处理。想到了dfs返回 ()内x的数量,但是具体细节还是写不出来,还得学习y总的手法。
代码
#include <iostream>
using namespace std;
int k;
string s;
int dfs() // dfs返回一个()的x
{
int res = 0;
while(k < s.size())
{
if(s[k] == '(')
{
k ++; // 跳过 (
res += dfs();
k ++; // 跳过 )
}else if(s[k] == '|')
{
k ++ ; // 跳过 |
res = max(res,dfs());
}else if(s[k] == ')') break;
else if(s[k] == 'x')
{
k ++;
res ++;
}
}
return res;
}
int main()
{
cin >> s;
cout << dfs() << endl;
return 0;
}
8、包子凑数(最大公因数 + 完全背包)
解题思路
求出所有数的最大公因数d,如果 d != 1 ,可以说明凑不到的数目有无穷多个,输出INF。
否则,我们通过完全背包来求(从n个物品中选k个数,组合类问题),猜想体积上界为10000。
定理:两个互斥的数p,q凑不到的最大整数:(p-1)*(q-1)-1
(对应题目 买不到的数目)
代码
#include <iostream>
using namespace std;
const int N = 10010;
int n;
bool f[110][N];
int a[110];
int gcd(int a,int b) // 求最大公因数
{
return b ? gcd(b,a % b) : a;
}
int main()
{
cin >> n;
int d = 0;
for(int i = 1;i <= n;i ++){
cin >> a[i];
d = gcd(d,a[i]);
}
if(d != 1) cout << "INF" << endl;
else
{
f[0][0] = true;
for(int i = 1;i <= n; i++)
for(int j = 0;j < N;j ++)
{
f[i][j] |= f[i-1][j];
if(j >= a[i]) f[i][j] |= f[i][j - a[i]]; // 完全背包
}
int res = 0;
for(int i = 0 ;i < N;i ++ ) {
if(!f[n][i])
res ++;
}
cout << res << endl;
}
return 0;
}
9、分巧克力(二分)
解题思路
二分。先假设出来最大的边长看符不符合,在答案范围内二分。时间复杂度O(nlogn)
代码
#include <iostream>
using namespace std;
const int N = 100010;
int n,k;
int h[N],w[N];
bool check(int mid)
{
int sum = 0;
for(int i = 1;i <= n;i ++)
{
sum += (h[i] / mid) * (w[i] / mid);
}
return sum >= k;
}
int main()
{
cin >> n >> k;
int l = 1,r;
for(int i = 1;i <= n ;i ++)
{
cin >> h[i] >> w[i];
r = max(r,h[i]);
r = max(r,w[i]);
}
// 二分
while(l < r)
{
int mid = l + r + 1 >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
cout << r << endl;
return 0;
}
10、油漆面积(线段树,不会)
解题思路
如果没有覆盖,可以用二维差分+前缀和。覆盖了,不会线段树就暴力循环骗点分。(开bool数组空间会更小)
其他人的题解