第八届蓝桥杯题解

1.迷宫

一道dfs的题目

#include<bits/stdc++.h>
using namespace std;
#define maxn 10
string str = "UDDLUULRULUURLLLRRRURRUURLDLRDRUDDDDUUUUURUDLLRRUUDURLRLDLRLULLURLLRDURDLULLRDDDUUDDUDUDLLULRDLUURRR";
char maps[10][10];
int vis[10][10];
int cou=0;
void dfs(int x,int y){
	if(vis[x][y]==1) return;
	if(x<0||x>9||y<0||y>9){
		cou++;
		return;
	}
	vis[x][y]=1;
	switch(maps[x][y]){
		case 'U':
			x-=1;
			break;
		case 'D':
			x+=1;
			break;
		case 'L':
			y-=1;
			break;
		case 'R':
			y+=1;
			break;
		default:
			break;
	}
	dfs(x,y);
}
int main(){
	int index;
	for(int i=0;i<10;i++){
		for(int j=0;j<10;j++){
			index=i*10+j;
			maps[i][j]=str[index];
		}
	}
	for(int i=0;i<10;i++){
		for(int j=0;j<10;j++){
			memset(vis,0,sizeof(vis));
			dfs(i,j);
		}
	}
	cout<<cou<<endl;
}

2 跳蚱蜢

可以将蚱蜢跳看做是盘子在跳,将初次摆放顺序看作012345678,最后的摆放顺序看作087654321,用bfs的方法解答

#include<bits/stdc++.h>
using namespace std;
struct node
{
    string s;
    int t;
    node(string ss, int tt){
		s = ss, t = tt;
	}
};
map<string,bool> mp;
queue<node> q;
void f()
{
    while(!q.empty()){
        node now = q.front();
        q.pop();
        string s = now.s;int t = now.t;
        if(s == "087654321"){
            cout<<t<<endl;
            break;
        }
        int i;
        for(i=0;i<10;i++){
            if(s[i]=='0') break;
        }
        for(int j=i-2;j<=i+2;j++){
            int k = (j+9)%9;
            if(k==i) continue;
            char tmp;
            tmp=s[i];s[i]=s[k];s[k]=tmp;
            if(!mp[s]){
                mp[s] = true;
                q.push(node(s,t+1));
            }
            tmp=s[i];
			s[i]=s[k];
			s[k]=tmp;
        }
    }
}
int main(){
	string s = "012345678";
	q.push(node(s, 0));
	mp[s] = true;
	f();
}

3 方块切割

观察发现每一个符合条件的切法都经过(3,3)
于是用dfs从(3,3)开始搜索,直到搜到边界,注意走到一个点时其关于(3,3)的另一个点也要标记,否则无法对称,最后结果要除以4,因为旋转对称的只算一种

#include<bits/stdc++.h>
using namespace std;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int maps[10][10];
int ans=0;
void dfs(int x,int y){
	if(x==0||x==6||y==0||y==6){
		ans++;
		return;
	}
	for(int i=0;i<4;i++){
		int dx=x+dir[i][0];
		int dy=y+dir[i][1];
		if(maps[dx][dy]==0){
			maps[dx][dy]=1;
			maps[6-dx][6-dy]=1;
			dfs(dx,dy);
			maps[dx][dy]=0;
			maps[6-dx][6-dy]=0;
		}
	}
}
int main(){
	maps[3][3]=1;
	dfs(3,3);
	cout<<ans/4<<endl;
}

4.字母组串

一种递归的思想,长度为n的字串由长度为n-1的子串分别加上a,b,c变化而来

#include <stdio.h>
int f(int a, int b, int c, int n)
{
	if(a<0 || b<0 || c<0) return 0;
	if(n==0) return 1; 
	
	return f(a-1,b,c,n-1) + f(a,b-1,c,n-1) + f(a,b,c-1,n-1);
}
int main()
{
	printf("%d\n", f(1,1,1,2));
	printf("%d\n", f(1,2,3,3));
	return 0;
}


5 最大公共子串

#include <stdio.h>
#include <string.h>

#define N 256
int f(const char* s1, const char* s2)
{
	int a[N][N];
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	int i,j;
	
	memset(a,0,sizeof(int)*N*N);
	int max = 0;
	for(i=1; i<=len1; i++){
		for(j=1; j<=len2; j++){
			if(s1[i-1]==s2[j-1]) {
				a[i][j] =a[i-1][j-1]+1;
				if(a[i][j] > max) max = a[i][j];
			}
		}
	}
	return max;
}

int main()
{
	printf("%d\n", f("abcdkkk", "baabcdadabc"));
	return 0;
}

6.正则问题

题目理解:遇到“|”就比较其左右两边的大小 如样例((xx|xxx)x|(x|xx))xx
(xx|xxx)的长度为3,遇到x加上1得4,(x|xx)=2,4|2=4,遇到
xx得到6
题解:用递归的方式求解,遇到‘(’时就递归到下一层,如果是x就用一个temp记录x的个数,遇到“|”时,由于“|”右边要和左边的x个数比大小,就用一个m记录左边的值,遇到右括号的时候就比较两个大小,返回较大的那一个

#include<bits/stdc++.h>
using namespace std;
string s;
int len;
int pos;
int f(){
	int m=0;
	int temp=0;
	while(pos<len){
		if(s[pos]=='('){
			pos++;
			temp+=f();
		}
		else if(s[pos]=='x'){
			pos++;
			temp++;
		}
		else if(s[pos]=='|'){
			pos++;
			m=max(m,temp);
			temp=0;
		}
		else if(s[pos]==')'){
			pos++;
			m=max(m,temp);
			return m;
		}
	}
	m=max(m,temp);
	return m;
}
int main(){
	cin>>s;
	len=s.size();
	int ans=f();
	cout<<ans<<endl;
}

7 包子凑数

如果输入的数的最大公约数不为1,那么就会有无数种数目是凑不出的,比如最大公约数是3,那么选出n笼后的结果就一定是3的倍数,这样不是3的倍数的数字就凑不出了,最大公约数是一,那就成了一个背包问题用j表示容量,如果j-a[i]可以表示,那么j也可以表示

#include<bits/stdc++.h>
using namespace std;
int f[110*110];
int a[200];
int gcd(int a,int b){
	if(b==0) return a;
	return gcd(b,a%b); 
}
int main(){
	int n,num,ans=0;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	num=gcd(a[0],a[1]);
	for(int i=2;i<n;i++){
		num=gcd(a[i],num);
	}
	if(num!=1){
		cout<<"INF"<<endl;
		return 0;
	}
	f[0]=1;
	for(int i=0;i<n;i++){
		for(int j=a[i];j<=10001;j++){
			if(f[j-a[i]]) f[j]=1;
		}
	}
	for(int i=0;i<10001;i++){
		if(!f[i]) ans++;
	}
	cout<<ans<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值