蓝桥杯4道例题(5)

题目难度由低到高

1.错误的票据
来源:第四届蓝桥杯省赛C++A/B组
题目链接
在这里插入图片描述
题解:找出最大和最小的数,同时再用一个数组记录每个数字的个数,最后遍历一遍即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=10010,M=100010;

int cnt[M];

int main(){
    
    
    int line,i=0,Min=100001,Max=0,a;
    int n,m; //m表示断号ID,n表示重号ID
    cin>>line;
    while(line--){
    
    
        while(cin>>a){
    
    
            cnt[a]++;
            Max=max(Max,a);
            Min=min(Min,a);
        }
    }

    for(int j=Min;j<Max;j++){
    
    
        if(cnt[j]==0) m=j;
        else if(cnt[j]==2) n=j;
    }

    cout<<m<<" "<<n<<endl;
    return 0;
}



java:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {
    
    
    static int N = 1000010;
    static boolean[] f = new boolean[N];
    static int cid ;
    static int did ;
    public static void main(String[] args) throws IOException {
    
    
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(reader.readLine().trim());
        int maxv = Integer.MIN_VALUE;
        int minv = Integer.MAX_VALUE;
        while(n -- > 0)
        {
    
    
            String[] s1 = reader.readLine().split(" ");
            for(int i = 0;i < s1.length;i++)
            {
    
    
                int t = Integer.parseInt(s1[i]);
                maxv = Math.max(maxv, t);
                minv = Math.min(minv, t);
                if(f[t]) cid = t;
                f[t] = true;
            }
        }
        for(int i = minv ;i <= maxv ;i ++)
        {
    
    
            if(!f[i])
            {
    
    
                did = i;
                break;
            }
        }
        System.out.println(did + " " + cid);
    }

}



2. 全球变暖
来源:第九届蓝桥杯省赛C++A/B组
题目链接

在这里插入图片描述
题解:我们通过dfs查询每一个岛屿,如果这个岛屿不会沉,就记录下来,然后用dfs查询到的总岛屿减去不会沉的岛屿即可;
c++代码:

#include <iostream>
#include <iomanip>
#include <string>
#include <string.h>
using namespace std;
const int N = 1100;
char maps[N][N];
bool biao[N][N];
int ways[4][2] = {
    
    {
    
    1, 0}, {
    
    0, 1}, {
    
    -1, 0}, {
    
    0, -1}}; //上下左右
int ans;
int v;
void dfs(int x, int y)
{
    
    
	biao[x][y] = false;
	if (maps[x + 1][y] == '#' && maps[x - 1][y] == '#' && maps[x][y + 1] == '#' && maps[x][y - 1] == '#' && v == 1) //用v作标记,因为一个岛屿可能有多个满足要求的点
	{
    
    
		ans++;
		v = 0; //这里不能直接退出函数,dfs必须把所有点都标记完,不然以后查找会出现重复
	}
	for (int i = 0; i <= 3; i++)
	{
    
    
		int nx = x + ways[i][0];
		int ny = y + ways[i][1];
		if (maps[nx][ny] == '#' && biao[nx][ny]) //满足条件继续搜索
			dfs(nx, ny);
	}
}
int main()
{
    
    
	int n;
	cin >> n;
	memset(biao, true, sizeof biao);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
    
    
			cin >> maps[i][j];
		}
	int yjl = 0;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
    
    
			if (maps[i][j] == '#' && biao[i][j])
			{
    
    
				v = 1;
				yjl++;
				dfs(i, j);
			}
		}
	cout << yjl - ans << endl; //总岛数减去不会沉的
}

java代码:

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main{
    
    
    static int N = 1010;
    static int n;
    static char[][] g = new char[N][N];
    static boolean[][] st = new boolean[N][N];
    static int[] dx = new int[] {
    
    -1,0,1,0};
    static int[] dy = new int[] {
    
    0,1,0,-1};
    static boolean bfs(int x,int y)
    {
    
    
        Queue<PIIs> q = new LinkedList<PIIs>();
        q.add(new PIIs(x,y));
        st[x][y] = true;
        int total = 0;//当前位置连通陆地的数量
        int bound = 0;//被淹没陆地的数量
        while(!q.isEmpty())
        {
    
    
            PIIs t = q.poll();
            total ++;
            boolean is_bound = false;//判断岛屿是否被淹没
            for(int i = 0;i < 4;i++)
            {
    
    
                int a = t.x + dx[i];
                int b = t.y + dy[i];
                if(a < 0 || a >= n || b < 0 || b >= n) continue;
                if(st[a][b]) continue;
                if(g[a][b] == '.') 
                {
    
    
                    is_bound = true;
                    continue;
                }
                q.add(new PIIs(a,b));
                st[a][b] = true;


            }
            if(is_bound) bound ++;
        }

        return total == bound;
    }
    public static void main(String[] args) {
    
    
        Scanner scan = new Scanner(System.in);
        n = scan.nextInt();
        for(int i = 0;i < n;i++)
        {
    
    
            char[] charArray = scan.next().toCharArray();
            for(int j = 0;j < n;j++)
            {
    
    
                g[i][j] = charArray[j];
            }
        }
        int cnt = 0;
        for(int i = 0;i < n;i++)
        {
    
    
            for(int j = 0;j < n;j++)
            {
    
    
                if(!st[i][j] && g[i][j] == '#')
                {
    
    
                    if(bfs(i,j)) cnt ++;
                }
            }
        }
        System.out.println(cnt);
    }
}
class PIIs
{
    
    
    public int x;
    public int y;
    public PIIs(int x,int y)
    {
    
    
        this.x = x;
        this.y = y;
    }
}



3.波动数列
来源:第五届蓝桥杯省赛C++A组
题目链接

在这里插入图片描述
题解:这题如果数字小一点可以通过dfs直接搜索,可是如此大的数字很明显是不行的;
我们设首相为t,F(i)={a,-b},第一个数t,第二个数t+F(1),第三个数t+F(1)+F(2)…,然后我们对这些数做和,可得到
nt + (n-1)F(1) + (n-2)F(2) + … +F(n-1) =s ,在变形一下,nt = s - {(n-1)F(1) + (n-2)F(2) + … +F(n-1)},那么只要右边的能整除n就满足条件(因为首项t是不确定的);然后我们发现(n-1)+(n-2)+…+1 在n确定时是个定值,也就是a和-b的总数是一定的,那么我们知道a的数目,就可以知道b的数目,也就能判断是否满足条件,现在我们只要求方案数即可,我们把(n-1)F(1)看做一个大小为n-1的货,其他依次类比,这就转化为了01背包求方案数的问题。
c++代码:

#include<iostream>
using namespace std;
#define MOD 100000007  
#define MAXN 1100  
long long  n,s,a,b; 
long long all;
long long Bo[MAXN*MAXN];

void fun_dp()//求方案数
{
    
    
	long long i,j;
	
	Bo[0]=1;//什么都没有是一种方案
	for(i=1;i<n;i++)//枚举货物,假设货物全部为a
	{
    
    
		
		for(j=i*(i+1)/2;j>=0;j--)//(j代表a的个数)(i*(i+1)/2 代表有大小为i的货物时最大的体积,我们把(n-1)F(1) + (n-2)F(2) + ....... +F(n-1)放过来看了
		{
    
    
			if(i<=j )
			{
    
    
				Bo[j] = (Bo[j] + Bo[j-i]) % MOD;//求a为j时的方案数,为j时是满足的,j-i  然后把此时的货物放进去也是满足的
			}else{
    
    
			    Bo[j] = Bo[j];	//放不进去
			} 
		}
	}
}
int fun_sum()
{
    
    
	long long count=0,i;
	long long temp;
	for(i=0;i<=all;i++)
	{
    
    
		temp = s - i*a + (all - i)*b;//满足条件
		if(temp%n == 0)
		{
    
    
			count = (count+Bo[i])%MOD;
		}
	}
	return count;
}
int main()
{
    
    
	long long count; 
	cin >> n >> s >> a >> b;
	all = n*(n-1)/2; //最多可以增加多少个a(背包容量最大值) 
	fun_dp();//进行动态规划的函数
	count = fun_sum();//统计总数
	cout << count;	
	return 0;
}

java代码:

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    
    
    static final int mod=100000007;
    static long n,s,a,b;
    static long all;
    static long Bo[]=new long[1100*1100];


    public static void main(String[] args) {
    
    
        Scanner sc=new Scanner(System.in);
        n=sc.nextLong();
        s=sc.nextLong();
        a=sc.nextLong();
        b=sc.nextLong();
        all = n*(n-1)/2; //最多可以增加多少个a(背包容量最大值)
        long count;
        fun_dp();//进行动态规划的函数
        count = fun_sum();//统计总数
        System.out.println(count);

    }
  static   void fun_dp()//求方案数
    {
    
    
        int i,j;

        Bo[0]=1;//什么都没有是一种方案
        for(i=1;i<n;i++)//枚举货物,假设货物全部为a
        {
    
    

            for(j=i*(i+1)/2;j>=0;j--)//(j代表a的个数)(i*(i+1)/2 代表有大小为i的货物时最大的体积,我们把(n-1)F(1) + (n-2)F(2) + ....... +F(n-1)放过来看了
            {
    
    
                if(i<=j )
                {
    
    
                    Bo[j] = (Bo[j] + Bo[j-i]) % mod;//求a为j时的方案数,为j时是满足的,j-i  然后把此时的货物放进去也是满足的
                }else{
    
    
                    Bo[j] = Bo[j];	//放不进去
                }
            }
        }
    }
  static   long fun_sum()
    {
    
    
         long count=0;
         long temp;
         int i;
        for(i=0;i<=all;i++)
        {
    
    
            temp = s - i*a + (all - i)*b;//满足条件
            if(temp%n == 0)
            {
    
    
                count = (count+Bo[i])%mod;
            }
        }
        return count;
    }
}

4.糖果
来源:第十届蓝桥杯省赛C++A组
题目链接
在这里插入图片描述
题解:最多只有20种口味,那么很明显是状态压缩dp了,我们开一个(1<<20)大小的数组用于储存每一种状态,剩下的就是类似背包来找最佳组合了;
c++代码:

#include <iostream>

using namespace std;
const int N = 1 << 20 + 5;
int dp[N], package[N];
int main()
{
    
    

    int n, k, m;
    cin >> n >> m >> k;
    int a;

    for (int i = 1; i <= n; i++)
    {
    
    
        for (int j = 1; j <= k; j++)
        {
    
    
            cin >> a;
            package[i] |= 1 << (a - 1); //因为一开始已经有一位了,故只需要移动a-1位
        }

        dp[package[i]] = 1; //每一包都是一个状态,故存在的状态初始为1
    }
    for (int i = 1; i <= n; i++)           //01背包?
        for (int j = 1; j < (1 << m); j++) //枚举每一个状态
        {
    
    
            if (dp[j] == 0) //说明暂时还没有存在这种状态
                continue;
            if (dp[j | package[i]] == 0 || dp[j] + 1 < dp[j | package[i]]) //能通过第i包糖引出一个新的状态,或优化一个存在的状态
                dp[j | package[i]] = dp[j] + 1;
        }
    if (dp[(1 << m) - 1] == 0)
        cout << "-1" << endl;
    else
    {
    
    
        cout << dp[(1 << m) - 1] << endl;
    }
}

java代码:

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    
    
    static final int N=1<<20+5;
    static int dp[]=new int[N];
    static int packages[]=new int[105];


    public static void main(String[] args) {
    
    
        Scanner sc=new Scanner(System.in);
        int n,k,m;
        n=sc.nextInt();
        m=sc.nextInt();
        k=sc.nextInt();
        int a;

        for (int i = 1; i <= n; i++)
        {
    
    
            for (int j = 1; j <= k; j++)
            {
    
    
                a=sc.nextInt();
                packages[i] |= 1 << (a - 1);//因为一开始已经有一位了,故只需要移动a-1位
            }

            dp[packages[i]] = 1; //每一包都是一个状态,故存在的状态初始为1
        }
        for (int i = 1; i <= n; i++)           //01背包?
            for (int j = 1; j < (1 << m); j++) //枚举每一个状态
            {
    
    
                if (dp[j] == 0) //说明暂时还没有存在这种状态
                    continue;
                if (dp[j | packages[i]] == 0 || dp[j] + 1 < dp[j | packages[i]]) //能通过第i包糖引出一个新的状态,或优化一个存在的状态
                dp[j | packages[i]] = dp[j] + 1;
            }
        if (dp[(1 << m) - 1] == 0)
            System.out.println("-1");
        else
        {
    
    
            System.out.println(dp[(1 << m) - 1]);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/jahup/article/details/107405111