第四届蓝桥杯本科A组解题报告(和B组相同的题目详见B组解题报告)

<1>高斯日记

见B组解答

 

<2>排他平方数
639172

package JiaNan;
import java.math.BigInteger;

public class PaiTaPingFangShu
{
	static int c[] = new int[7];            //存储这个六位数
	static boolean vis[] = new boolean[11]; //记录0-9这10个数字是否被访问
	/*
	 * 回溯,求出前6个数字的全排列
	*/
	static void dfs(int start,int n)
	{
		if(start == 7)
		{
			check(c);
		    return;
		}
		for(int i = 0;i <= n;i++)
		{
			if(!vis[i])
			{
			    c[start] = i;
			    vis[i] = true;
			    dfs(start+1,n);
			    vis[i] = false;
			}
		}
		
	}
	/*
	 * 判断这个6位数字是否是排他平方数
	*/
	
	static void check(int c[])
	{
		int sum = 0;
		for(int i = 1;i <= 6;i++)
		{
		   sum = sum*10 + c[i];
		}
		
		String s1 = ""+sum;
		if(s1.length() != 6)
			return;
		BigInteger m = BigInteger.valueOf(sum).multiply(BigInteger.valueOf(sum));
		String s2 = ""+m;
		if(EveryCharIsDifferent(s1,s2))
			System.out.println(s1);
	}
	/*
	 * 如果s1中的每个字符都不同于s2中的字符,则返回true,否则false
	 */
	static boolean EveryCharIsDifferent(String s1,String s2)
	{
		for(int i = 0;i < s1.length();i++)
			for(int j = 0;j < s2.length();j++)
			{
				if(s1.charAt(i) == s2.charAt(j))
					return false;
			}
		return true;
		
	}
	
	/*
	 * 
	 */
	public static void main(String args[])
	{
		long start = System.nanoTime();
		dfs(1,9);
		long end = System.nanoTime();
		System.out.println("运行时间:"+(end-start)/Math.pow(10, 9)+"s"); 
	}
} 

/*
203879
639172
运行时间:0.194841155s
*/


<3>振兴中华
35

package JiaNan;

public class PaiTaPingFangShu
{
	static String s[] = new String[10];
	static int kinds = 0;
	static void dfs(int start,int x,int y)
	{
       if(x==1 && y==1)
       {
    	   for(int i = 1;i < start;i++)
    		   System.out.print(s[i]);
    	   System.out.println();
    	   kinds++;
       }
       for(int i = 0;i <= 1;i++)
       {
    	   if(i==0 && x-1>0)
    	   {
    		   s[start] = "右 ";
    		   dfs(start+1,x-1,y);
    	   }
    	   else
    	   {
    		   if(i==1 && y-1>0)
    		   {
    			   s[start] = "下 ";
    			   dfs(start+1,x,y-1);
    		   }
    	   }
       }
	}
	public static void main(String args[])
	{
		long start = System.nanoTime();
		dfs(1,5,4);
		System.out.println("一共有"+kinds+"种情况");
		long end = System.nanoTime();
		System.out.println("运行时间:"+(end-start)/Math.pow(10, 9)+"s"); 
	}
} 

/*
右 右 右 右 下 下 下 
右 右 右 下 右 下 下 
右 右 右 下 下 右 下 
右 右 右 下 下 下 右 
右 右 下 右 右 下 下 
右 右 下 右 下 右 下 
右 右 下 右 下 下 右 
右 右 下 下 右 右 下 
右 右 下 下 右 下 右 
右 右 下 下 下 右 右 
右 下 右 右 右 下 下 
右 下 右 右 下 右 下 
右 下 右 右 下 下 右 
右 下 右 下 右 右 下 
右 下 右 下 右 下 右 
右 下 右 下 下 右 右 
右 下 下 右 右 右 下 
右 下 下 右 右 下 右 
右 下 下 右 下 右 右 
右 下 下 下 右 右 右 
下 右 右 右 右 下 下 
下 右 右 右 下 右 下 
下 右 右 右 下 下 右 
下 右 右 下 右 右 下 
下 右 右 下 右 下 右 
下 右 右 下 下 右 右 
下 右 下 右 右 右 下 
下 右 下 右 右 下 右 
下 右 下 右 下 右 右 
下 右 下 下 右 右 右 
下 下 右 右 右 右 下 
下 下 右 右 右 下 右 
下 下 右 右 下 右 右 
下 下 右 下 右 右 右 
下 下 下 右 右 右 右 
一共有35种情况
运行时间:0.00814562s
*/


<4>颠倒的价牌
9088

package JiaNan;
public class DianDaoDeJiaPai
{
    static int choice[] = new int[]{1,2,5,6,8,9,0};
    static int c[] = new int[5];       //存储可能的价格
    static boolean vis[] = new boolean[8]; 
    static int zhuan[] = new int[50],indexZhuan = 0;
    static int pei[] = new int[50],indexPei = 0,yuanjia[] = new int[50];
    /*
     * 
     */
    static void dfs(int start,int n)   //start = 1,n = 7;
    {
    	if(start == 5)
    	{
    		if(c[1]==0 || c[4]==0)
    			return;
    		int yuan = c[1]*1000 + c[2]*100 + c[3]*10 + c[4];
    		int diandao = changeTo(c[4])*1000 + changeTo(c[3])*100 + changeTo(c[2])*10 + changeTo(c[1]);
    		if(yuan-diandao>200 && yuan-diandao<300)
    		{
    			pei[indexPei] = yuan - diandao;
    			yuanjia[indexPei] = yuan;
    			indexPei++;
    		}
    		if(diandao-yuan>800 && diandao-yuan<900)
    		{
    			zhuan[indexZhuan++] = diandao-yuan;	
    		}
    		return;
    	}
    	for(int i = 0;i < n;i++)
    	{		
    		 c[start] = choice[i];
    		 dfs(start+1,n);
    	}
    }
    
    /*
     * 
     */
    static int changeTo(int num)
    {
    	switch(num)
    	{
    	case 9:
    		return 6;
    	case 6:
    		return 9;
    	default:
    		return num;
    	}
    }
	public static void main(String args[])
	{
		dfs(1,7);
		for(int i = 0;i < indexZhuan;i++)
			for(int j = 0;j < indexPei;j++)
			{
				if(zhuan[i]-pei[j]==558)
				{
					System.out.println(zhuan[i]+" "+pei[j]);
					System.out.println(yuanjia[j]);
					return;
				}
			}
	}
}

/*
840 282
9088
*/

<5>前缀判断

见B组解答

 

<6>逆波兰表达式

x+v1.n+1

 

正常的表达式称为中缀表达式,运算符在中间,主要是给人阅读的,机器求解并不方便。

例如:

3 + 5 * (2 + 6) - 1

而且,常常需要用括号来改变运算次序。相反,如果使用逆波兰表达式(前缀表达式)表示,上面的算式则表示为:

- + 3 * 5 + 2 6 1

不再需要括号,机器可以用递归的方法很方便地求解。为了简便,我们假设:

1.只有+ - *三种运算符

2.每个运算数都是一个小于10的非负整数

下面的程序对一个逆波兰表示串进行求值。

其返回值为一个结构:其中第一元素表示求值结果,第二个元素表示它已解析的字符数。

#include<iostream>
using namespace std;
struct EV 
{ 
	int result; 
	int n; 
};  

struct EV evaluate(char* x) 
{ 
	
	struct EV ev = {0,0}; 
	struct EV v1; 
	struct EV v2; 
	
	if(*x==0) return ev; 
	
	if(x[0]>='0' && x[0]<='9')
	{ 	
		ev.result = x[0]-'0'; 
		ev.n = 1; 
		return ev; 
	} 
	
	v1 = evaluate(x+1); 
	v2 = evaluate(x+v1.n+1);    //填空
	
	if(x[0]=='+') ev.result = v1.result + v2.result; 
	
	if(x[0]=='*') ev.result = v1.result * v2.result;  
	
	if(x[0]=='-') ev.result = v1.result - v2.result; 
	
	ev.n = 1+v1.n+v2.n; 
	return ev; 	
}  

void main()
{
	char* str =  "-+3*5+261"; 
	int n = evaluate(str).result;
	cout<<n<<endl;
}

/*
42
*/

<7>错误票据

见B组解答


<8>买不到的数字

#include<iostream>
#include<ctime>
using namespace std;
bool flag = false;     //这个发现并不能写出一个带有回溯性质的,且有返回值的函数,因此在此我用了个bool类型的变量来记录

///
void isComprise(int N,int smallNum,int largerNum)
{
	if(N < smallNum)
	{
	    return;
	}
	if(N==smallNum || N == largerNum || N==smallNum+largerNum)
	{
		flag = true;
		return;
	}
	for(int i = 0;i <= 1;i++)
	{
		if(i == 0)
		{
			isComprise(N-smallNum,smallNum,largerNum);
		}
		else
		{
			if(i == 1)
			{
				isComprise(N-largerNum,smallNum,largerNum);
			}
		}
	}	
}

//
void main()
{
	
    int smallNum,largerNum;
	cin>>smallNum>>largerNum;
    double start = clock();
	int maxCannotCompriseNum = 5*largerNum;   //存储这个最大不能组成的数字,先假设是这个较大数字的5倍
	while(1)
	{
        isComprise(maxCannotCompriseNum,smallNum,largerNum);
		if(!flag)
		{
			cout<<maxCannotCompriseNum<<endl;
			break;
		}
        maxCannotCompriseNum--;
		flag = false;
	}
	double end = clock();
	cout<<"运行时间:"<<(end-start)/CLOCKS_PER_SEC<<"s"<<endl;
}

/*
4 7
17
运行时间:0.001s
*/


 

<10>大臣的旅费

很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。

为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。

J是T国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。他有一个钱袋,用于存放往来城市间的路费。

聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。

J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?

输入格式:

输入的第一行包含一个整数n,表示包括首都在内的T王国的城市数

城市从1开始依次编号,1号城市为首都。

接下来n-1行,描述T国的高速路(T国的高速路一定是n-1条)

每行三个整数Pi, Qi,Di,表示城市Pi和城市Qi之间有一条高速路,长度为Di千米。

输出格式:

输出一个整数,表示大臣J最多花费的路费是多少。

样例输入:

5

1 2 2

1 3 1

2 4 5

2 5 4

样例输出:

135

样例说明:

大臣J从城市4到城市5要花费135的路费。

资源约定:

峰值内存消耗 <64M

CPU消耗 < 5000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0

注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。

注意: 所有依赖的函数必须明确地在源文件中 #include<xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

#include<iostream>
using namespace std;
const int DEP = 1000;    //开始假设任何两座城市之间都没有修路,距离都是无限远
int c[101][101];         //存储两座城市之间的距离

void main()
{
    for(int i = 1;i <= 100;i++)
		for(int j = 1;j <= 100;j++)
		{
			if(i != j)
				c[i][j] = DEP;
			else
				c[i][j] = 0;
		}
		
		int n;               //n座城市
		cin>>n; 
		for(i = 1;i < n;i++)           //建立起城市之间距离的关系
		{
			int Pi,Qi,Di;
			cin>>Pi>>Qi>>Di;
			c[Pi][Qi] = c[Qi][Pi] = Di;
		}
		
		for(i = 1;i <= n;i++)
			for(int k = 1;k <= n;k++)
				for(int j = 1;j <= n;j++)
				{
					if(i!=k && k!=j && i!=j && c[i][k]!=DEP && c[k][j]!=DEP && c[i][j]==DEP)
					{
						c[i][j] = c[i][k] + c[k][j];
					}
				}
				
				int max = c[1][2];
				
				for(i = 1;i <= n;i++)
					for(int j = 1;j <= n;j++)
					{
                        if(c[i][j] > max)
							max = c[i][j];
					}
					cout<<(1+max)*max/2 + 10*max<<endl;
}

/*
第一组测试用例:
5
1 2 2
1 3 1
2 4 5
2 5 4
135

第二组测试用例:
6
1 2 2
1 3 1
2 4 5
2 5 4
3 6 10
351
思考:通过此题,我们是否可以用数组来模拟树形结构呢?因为可以得到权,,不过树的删除、增加操作会困难些
*/


 方法2(别人的,自己的有误)

#include<stdio.h>
#include<string.h>
int a[1000][1010];

int main()
{
    int i,j,k,n,x,y,z,max,sum;
    scanf("%d",&n);
	
    for(i=0;i<=n;i++)
        for(j=0;j<=n;j++)
            a[i][j]=999999;
		for(i=1;i<n;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			a[x][y]=z;
			a[y][x]=z;
		}
		max=sum=0;
		for(k=1;k<=n;k++)
			for(i=1;i<=n;i++)
				for(j=1;j<=n;j++)
					if(i!=j)
					{
						a[i][j]=a[i][k]+a[k][j]<a[i][j]?a[i][k]+a[k][j]:a[i][j];
					}
					for(i=0;i<=n;i++)
						for(j=0;j<=n;j++)
							if(a[i][j]<999999)
								max=a[i][j]>max?a[i][j]:max;
							for(i=1;i<=max;i++)
								sum+=(i+10);
							printf("%d\n",sum);
							return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值