<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;
}