【蓝桥杯】第八届蓝桥杯(2017)-省赛题解_C/C++__大学A组

题目就不贴了,记录一下自己做题的思路和代码.

详细题目链接

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,不会)

解题思路

附上其他大佬链接,看样子也是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数组空间会更小)
其他人的题解

猜你喜欢

转载自blog.csdn.net/weixin_43154149/article/details/109036812