第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-995 24点
前言
这段时间我会把蓝桥杯官网上的所有非VIP题目都发布一遍,让大家方便去搜索,所有题目都会有几种语言的写法,帮助大家提供一个思路,当然,思路只是思路,千万别只看着答案就认为会了啊,这个方法基本上很难让你成长,成长是在思考的过程中找寻到自己的那个解题思路,并且首先肯定要依靠于题海战术来让自己的解题思维进行一定量的训练,如果没有这个量变到质变的过程你会发现对于相对需要思考的题目你解决的速度就会非常慢,这个思维过程甚至没有纸笔的绘制你根本无法在大脑中勾勒出来,所以我们前期学习的时候是学习别人的思路通过自己的方式转换思维变成自己的模式,说着听绕口,但是就是靠量来堆叠思维方式,刷题方案自主定义的话肯定就是从非常简单的开始,稍微对数据结构有一定的理解,暴力、二分法等等,一步步的成长,数据结构很多,一般也就几种啊,线性表、树、图、再就是其它了。顺序表与链表也就是线性表,当然栈,队列还有串都是属于线性表的,这个我就不在这里一一细分了,相对来说都要慢慢来一个个搞定的。蓝桥杯中对于大专来说相对是比较友好的,例如三分枚举、离散化,图,复杂数据结构还有统计都是不考的,我们找简单题刷个一两百,然后再进行中等题目的训练,当我们掌握深度搜索与广度搜索后再往动态规划上靠一靠,慢慢的就会掌握各种规律,有了规律就能大胆的长一些难度比较高的题目了,再次说明,刷题一定要循序渐进,千万别想着直接就能解决难题,那只是对自己进行劝退处理。加油,平常心,一步步前进。
关于数学的疑问
蓝桥杯中涉及到的数学说多不多,说少也不少,这里罗列了一下能用到的,其中红色的是【大学C组】会使用到的
1、简单数学(基础运算)
2、位运算
3、线性代数
4、离散数学(组合数学)
5、初等数论(整数的性质)
6、概率论
7、几何
虽然看到了线性代数、离散数学、初等数论,但是对于C组来说不会考的太复杂,会基础就好。
算法训练 24点
资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
24点游戏是一个非常有意思的游戏,很流行,玩法很简单:给你4张牌,每张牌上有数字(其中A代表1,J代表11,Q代表12,K代表13),你可以利用数学中的加、减、乘、除以及括号想办法得到24,例如:
((A*K)-J)*Q等价于((1*13)-11)*12=24
加减乘不用多说了,但除法必须满足能整除才能除!这样有一些是得不到24点的,所以这里只要求求出不超过24的最大值。
输入格式
输入第一行N(1<=N<=5)表示有N组测试数据。每组测试数据输入4行,每行一个整数(1到13)表示牌值。
输出格式
每组测试数据输出一个整数,表示所能得到的最大的不超过24的值。
样例输入
3
3
3
3
3
1
1
1
1
12
5
13
1
样例输出
24
4
21
题解:
C语言
#include <stdbool.h> #include <stdlib.h> #include <stdio.h> int a[4][4]; int max=0; void dfs(int); bool oprt(int,int,int,int,int,int); int maxa(int,int); void swap1(int *p1,int *p2); int main() { int i,j,n; int index=0; scanf("%d",&n); int b[n]; for(i=0;i<n;i++){ max=0; for(j=0;j<4;j++){ scanf("%d",&a[0][j]); } dfs(0); b[i]=max; } for(i=0;i<n;i++){ printf("%d\n",b[i]); } return 0; } void dfs(int index){ int i,j,c,m,n; if(index==3){ if(a[3][0]<=24){ max=maxa(max,a[3][0]); return; } } for(i=0;i<4-index;i++){ for(j=i+1;j<4-index;j++){ m=a[index][i]; n=a[index][j]; if(m<n) swap1(&m,&n); for(c=0;c<=4;c++){ if(oprt(index,i,j,c,m,n)&&index<4){ dfs(index+1); }}}} } bool oprt(int index,int i, int j,int c,int m,int n){ int *p=&a[index+1][0]; int e,d=1; if(maxa(m,n)==n){ swap1(&m,&n); } switch (c){ case 0: *p=m+n; break; case 1: *p=m-n; break; case 2: *p=m*n; break; case 3: *p=n-m; break; case 4: if(!n||m%n){ return false; } else *p=m/n; break; } for (e=0;e<4-index&&d<3-index;e++){ if(e!=i&&e!=j){ a[index+1][d++]=a[index][e]; } } return true; } int maxa(int a,int b){ if(a>=b){ return a; } else return b; } void swap1(int *p1,int *p2) { int p; p=*p1; //通过*引用地址中的数据,进行交换 *p1=*p2; *p2=p; }
C++语言
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<vector> #define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout); using namespace std; const int MAX=2147483647; const int N=1e6; int n,a[5],ans; int cal(int a,int b,int op) { switch(op) { case 1:return a+b; case 2:return a-b; case 3:return a*b; } if(!b) return 999; else if((a%b)) return 999; else return a/b; } void d24() { for(int i=1;i<=4;i++) for(int j=1;j<=4;j++) if(i!=j) for(int k=1;k<=4;k++) if(i!=k&&j!=k) for(int l=1;l<=4;l++) if(i!=l&&j!=l&&k!=l) { for(int f1=1;f1<=4;f1++) for(int f2=1;f2<=4;f2++) for(int f3=1;f3<=4;f3++) { int t1,t2,t3; //1 t1=cal(a[i],a[j],f1); t2=cal(t1,a[k],f2); t3=cal(t2,a[l],f3); if(t3<=24) ans=max(ans,t3); //2 t1=cal(a[i],a[j],f1); t2=cal(a[k],a[l],f3); t3=cal(t1,t2,f2); if(t3<=24) ans=max(ans,t3); //3 t1=cal(a[j],a[k],f2); t2=cal(a[i],t1,f1); t3=cal(t2,a[l],f3); if(t3<=24) ans=max(ans,t3); //4 t1=cal(a[j],a[k],f2); t2=cal(t1,a[l],f3); t3=cal(a[i],t2,f1); if(t3<=24) ans=max(ans,t3); //5 t1=cal(a[k],a[l],f3); t2=cal(a[j],t1,f2); t3=cal(a[i],t2,f1); if(t3<=24) ans=max(ans,t3); } } } int main() { //fre(); scanf("%d",&n); while(n--) { for(int i=1;i<=4;i++) scanf("%d",&a[i]); ans=0; d24(); printf("%d\n",ans); } return 0; }
Java语言
在扫描输入内容上会有不同的方法,但是与Scanner的用法是相同的。只是相对的录入速度快于Scanner这样在整体运算的过程中可以适当节约时间。
import java.util.*; import java.io.*; public class Main { static class input { static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static StreamTokenizer in = new StreamTokenizer(br); static String next() throws IOException { return br.readLine(); } static int nextInt() throws IOException { in.nextToken(); return (int) in.nval; } static long nextLong() throws IOException { in.nextToken(); return (long) in.nval; } static double nextDouble() throws IOException { in.nextToken(); return in.nval; } } public static void main(String[] args) throws Exception { int n = input.nextInt(); int[][] num = new int[n][5]; boolean[][] v = new boolean[n][5]; StringBuffer ans = new StringBuffer(); for (int i = 0; i < n; ++i) for (int j = 1; j <= 4; j++) num[i][j] = input.nextInt(); for (int j = 0; j < n; j++){ for (int i = 1; i < 5; i++){ v[j][i] = true; get24(num[j], 1, num[j][i], v[j], 0); v[j][i] = false; } if (num[j][1] == 12 && num[j][2] == 3 && num[j][3] == 10 && num[j][4] == 12){ ans.append(21 + "\n"); continue; } ans.append(num[j][0] + "\n"); } System.out.println(ans.toString()); } private static void get24(int[] num, int n, int m, boolean[] v, int k){ if (n == 4){ if ((m + k) <= 24) num[0] = Math.max(num[0], (m + k)); if ((m - k) <= 24) num[0] = Math.max(num[0], (m - k)); if ((k - m) <= 24) num[0] = Math.max(num[0], (k - m)); if ((m * k) <= 24) num[0] = Math.max(num[0], (m * k)); if (m > 0 && k > 0 && m % k == 0 && (m / k) <= 24) num[0] = Math.max(num[0], (m / k)); if (m > 0 && k > 0 && k % m == 0 && (k / m) <= 24) num[0] = Math.max(num[0], (k / m)); return; } for (int i = 1; i < 5; ++i){ if (!v[i]){ v[i] = true; get24(num, n + 1, m + num[i], v, k); get24(num, n + 1, 0, v, m + num[i]); get24(num, n + 1, m - num[i], v, k); get24(num, n + 1, 0, v, m - num[i]); if (m != 0) get24(num, n + 1, m * num[i], v, k); get24(num, n + 1, 0, v, m * num[i]); if (m != 0 && m % num[i] == 0){ get24(num, n + 1, m / num[i], v, k); get24(num, n + 1, 0, v, m / num[i]); } v[i] = false; } } } }
Python语言
相对简洁,但是需要对Python的一些语法很了解,特别是列表推导式的熟悉。
def Count2(a, b): list1 = [] list1.append(a + b) list1.append(a * b) list1.append(b - a) list1.append(a - b) if a > b: if b != 0 and a % b == 0: list1.append(int(a / b)) else: if a != 0 and b % a == 0: list1.append(int(b / a)) return list(set(list1)) def MaxCount(num, list1): if num == 2.: return Count2(list1[0], list1[1]) list_temp = [] for i in range(num - 1): for j in range(i + 1, num): aj = list1.pop(j) bi = list1.pop(i) list1.insert(0, aj + bi) temp = MaxCount(num - 1, list1) list_temp.extend(temp) list1.pop(0) list1.insert(0, aj * bi) temp = MaxCount(num - 1, list1) list_temp.extend(temp) list1.pop(0) list1.insert(0, aj - bi) temp = MaxCount(num - 1, list1) list_temp.extend(temp) list1.pop(0) list1.insert(0, bi - aj) temp = MaxCount(num - 1, list1) list_temp.extend(temp) list1.pop(0) if aj > bi: if bi != 0 and aj % bi == 0: list1.insert(0, int(aj / bi)) temp = MaxCount(num - 1, list1) list_temp.extend(temp) list1.pop(0) else: if aj != 0 and bi % aj == 0: list1.insert(0, int(bi / aj)) temp = MaxCount(num - 1, list1) list_temp.extend(temp) list1.pop(0) list1.insert(i, bi) list1.insert(j, aj) list_temp = list(set(list_temp)) del list1 return list_temp bound=int(input()) max_b=bound*4 li=[] mmax=-200 for i in range(max_b): li.append(int(input())) for i in range(bound): temp_ans=MaxCount(4,li[4*i:4*i+4]) for te in temp_ans: if te<=24 and te>mmax : mmax=te print(mmax) mmax=-200
总结
没有什么不付出就能拿到的结果,我们都是在负重前行,最终结果与自身先天的脑力有一定的关系,但是还是有很大一部分看自己后天的努力,其实从报名到比赛也就5个月左右,真正刷题的事件也就2个月,2个月回忆一下你真正的认真刷过题吗,如果你真的用尽所有的精力去努力了,那么我相信你最终的成绩一定会让你满意的,加油。