【思特奇杯·云上蓝桥-算法集训营】第二周

  1. 带分数

问题描述

100 可以表示为带分数的形式:100 = 3 + 69258 / 714。

还可以表示为:100 = 82 + 3546 / 197。

注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。

类似这样的带分数,100 有 11 种表示法。

输入格式

从标准输入读入一个正整数N (N<1000*1000)

输出格式

程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。

注意:不要求输出每个表示,只统计有多少表示法!

样例输入1

100

样例输出1

11

样例输入2

105

样例输出2

6

#include <bits/stdc++.h>
using namespace std;
const int N =10;
int n;
int num[N];
int ans;//计数
int calc(int l , int r)
{
    int res = 0 ;
    for(int i = l ; i <= r ; i++)
       res = res*10 + num[i]; 
    return res;   
}

int main()
{
    cin>>n;
    for(int i = 1 ;i <= 9 ;i++)
        num[i-1] = i;
    do{
        for(int i = 0 ;i < 7 ;i++)
          for(int j = i + 1 ; j < 8 ;j++)
          {
              int a = calc( 0 , i);
              int b = calc( i + 1 , j);
              int c = calc( j + 1 , 8);
              if(a*c + b == n*c)  ans++;
          }
              
        
    }while(next_permutation(num , num +9));
    cout<<ans<<endl;
    return 0;
}
  1. 李白打酒

题目描述

话说大诗人李白,一生好饮。幸好他从不开车。

一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:

无事街上走,提壶去打酒。

逢店加一倍,遇花喝一斗。

这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。

请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。

int main()
{
    int wine,store,flower;
    
    scanf("%d%d%d",&wine,&store,&flower);
    LB(wine, store, flower);
    printf("%d\n",n);
    
    return 0;
}
 
int LB(int wine,int store,int flower)
{
    if (store>0) {
        LB(wine*2, store-1, flower);
    }
    if (flower>1) {
        LB(wine-1, store, flower-1);
    }
    if (wine==1&&store==0&&flower==1) {
        n++;
    }
    
    return n;
}
  1. 第39级台阶

题目描述:

    小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!

    站在台阶前,他突然又想着一个问题:

    如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?

输出格式:

输出一个整数

#include<cstdio>
using namespace std;
int ans=0;
void dfs(int sum,int s){
	if(sum==39){
		if(!(s&1)){
			ans++;
		}
	} 
	else if(sum>39) return ;
	else{		
		dfs(sum+1,s+1);
		dfs(sum+2,s+1);
	}
}
int main(){
	dfs(0,0);
	printf("%d\n",ans);
	return 0;
}
  1. 穿越雷区

题目描述

已知的地图是一个方阵,上面用字母标出了A,B区,其它区都标了正号或负号分别表示正负能量辐射区。

例如:

A + - + -

- + - - +

- + + + -

+ - + - +

B + - + -

坦克车只能水平或垂直方向上移动到相邻的区。

数据格式要求:

输入第一行是一个整数n,表示方阵的大小, 4<=n<100

接下来是n行,每行有n个数据,可能是A,B,+,-中的某一个,中间用空格分开。

A,B都只出现一次。

要求输出一个整数,表示坦克从A区到B区的最少移动步数。

如果没有方案,则输出-1

例如:

用户输入:

5

A + - + -

- + - - +

- + + + -

+ - + - +

B + - + -

则程序应该输出:

10

资源约定:

峰值内存消耗 < 512M

CPU消耗  < 1000ms

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

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

注意: main函数需要返回0

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

注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程

#include <stdio.h>
#include <string.h>
#define INF 1<<30
char map[105][105];
int dir[4][2]={-1,0,0,1,1,0,0,-1};
int n;
int vis[105][105];
int min=INF;
int f_x,f_y;
void dfs(int x,int y,int t,char ch) 
{
	if(x<=0 || x>n || y<=0 || y>n)
		return ;
	if(x==f_x && y==f_y)
	{
		if(t<min)
			min=t;
		return ;
	}
	for(int k=0;k<4;k++)
	{
		int px=x+dir[k][0],py=y+dir[k][1];
		if(!vis[px][py] && map[px][py]!=ch)
		{
			vis[px][py]=1;
			dfs(px,py,t+1,map[px][py]);
			vis[px][py]=0;
		}
	}
}
 
int main()
{
	int i,j;
	int s_x,s_y;
	memset(map,0,sizeof(map));
	memset(vis,0,sizeof(vis));
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
		{
			scanf("%*c%c",map[i]+j);
			if(map[i][j]=='A')
			{//开始点 
				s_x=i;
				s_y=j;
			}
			else if(map[i][j]=='B')
			{//终止点 
				f_x=i;
				f_y=j;
			}
		}
	}
	vis[s_x][s_y]=1;
	dfs(s_x,s_y,0,map[s_x][s_y]);
	if(min==INF)
		printf("-1");
	else
		printf("%d\n",min);
	return 0;
}
  1. 迷宫

题目描述

下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可 以通行的地方。

010000

000100

001001

110000

迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这 个它的上、下、左、右四个方向之一。 对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫, 一共 10 步。其中 D、U、L、R 分别表示向下、向上、向左、向右走。 对于下面这个更复杂的迷宫(30 行 50 列),请找出一种通过迷宫的方式, 其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。 请注意在字典序中D<L<R<U。(如果你把以下文字复制到文本文件中,请务 必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 maze.txt, 内容与下面的文本相同)

答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个字符串,包含四种字母 D、U、L、R,在提交答案时只填写这个字符串,填 写多余的内容将无法得分

#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
const int X[4] = {1,0,0,-1};
const int Y[4] = {0,-1,1,0};
const string S[4] = {"D","L","R","U"};
bool a[31][51];
struct Coordinate{
	int x,y;
	string s;
	Coordinate(int x,int y,string s):x(x),y(y),s(s){}
};
queue<Coordinate> q;
void bfs(){
	Coordinate t = q.front();
	q.pop();
	for(int i=0;i<4;i++){
		int tx = t.x + X[i];
		int ty = t.y + Y[i];
		if(tx<1||tx>30||ty<1||ty>50||a[tx][ty])continue;
		string ts = t.s + S[i];
		if(tx==30&&ty==50){
			while(!q.empty())q.pop();
			cout<<ts;
			return;
		}
		a[tx][ty]=true;
		q.push(Coordinate(tx,ty,ts));
	}
}
int main(){
	for(int i=1;i<=30;i++)for(int j=1;j<=50;j++){
		char ch;
		cin>>ch;
		a[i][j] = (ch=='1');
	}
	q.push(Coordinate(1,1,""));
	while(!q.empty())bfs();
	return 0;
}
  1. 跳马

问题描述:

中国象棋半张棋盘如图1所示。马自左下角(0,0)向右上角(m,n)跳。规定只能往右跳,不准往左跳。比如图1中所示为一种跳行路线,并将路径总数打印出来。

输入格式:

只有一行:两个数n,m

输出格式:

只有一个数:总方案数total。

#include <stdio.h>
#include <stdlib.h>
int m,n;
int totle=0;
void jump(int r,int c,int a,int b)
{
    if(r<0||r>m||c<0||c>n)
        return;
    if(r+a==m&&c+b==n)
    {
        totle++;
        return;
    }
    
    jump(r+a,c+b,2,1);
    jump(r+a,c+b,-2,1);
    jump(r+a,c+b,1,2);
    jump(r+a,c+b,-1,2);
}
int main()
{
    scanf("%d %d",&m,&n);
    jump(0,0,0,0);
    printf("%d",totle);
    return 0;
}
  1. 路径之谜

小明冒充X星球的骑士,进入了一个奇怪的城堡。

城堡里边什么都没有,只有方形石头铺成的地面。

假设城堡地面是 n x n 个方格。【如图1.png】所示。

按习俗,骑士要从西北角走到东南角。

可以横向或纵向移动,但不能斜着走,也不能跳跃。

每走到一个新方格,就要向正北方和正西方各射一箭。

(城堡的西墙和北墙内各有 n 个靶子)

同一个方格只允许经过一次。但不必做完所有的方格。

如果只给出靶子上箭的数目,你能推断出骑士的行走路线吗?

有时是可以的,比如图1.png中的例子。

本题的要求就是已知箭靶数字,求骑士的行走路径(测试数据保证路径唯一)

输入:

第一行一个整数N(0<N<20),表示地面有 N x N 个方格

第二行N个整数,空格分开,表示北边的箭靶上的数字(自西向东)

第三行N个整数,空格分开,表示西边的箭靶上的数字(自北向南)

输出:

一行若干个整数,表示骑士路径。

为了方便表示,我们约定每个小格子用一个数字代表,从西北角开始编号: 0,1,2,3....

比如,图1.png中的方块编号为:

0  1  2  3

4  5  6  7

8  9  10 11

12 13 14 15

示例:

用户输入:

4

2 4 3 4

4 3 3 3

程序应该输出:

0 4 5 1 2 3 7 11 10 9 13 14 15

资源约定:

峰值内存消耗 < 256M

CPU消耗  < 1000ms

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

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

注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。

注意:主类的名字必须是:Main,否则按无效代码处理。

#include<stdio.h>
int b[500] = {0}; 
int way[17] = {0}; 
int up[25] = {0}; 
int left[25] = {0};
int F = 0; 
int n ,n2 = n*n;
int ceshi()
{
	int i,s = 0;
	for(i = 0; i < n; i++)
	{
		if((up[i] == 0) && (left[i] == 0))
		{
			s++;
		}
		if(up[i % n] < 0 || left[i / n] < 0)return 0;
	} 
	if(s == n)return 1;
		return 0;
}
int f(int x,int k)
{
	int i,j;
	if(x==n2-1) 
	{
		if(ceshi() == 1)
		{	
			for(i = 0; i <= k; i++)
			{
				printf("%d ",way[i]);
			}
			F = 1;
		}
	}
	else if(F == 0)
	{ 
		for(i = 1; i < n2; i++)
		{
			if(b[i] == 0)
			{
				b[i] = 1;
				if((x+n == i) || (x-n == i) || ((x-1 == i) && (i%n != (n-1))) || ((x+1 == i)&& ((i%n != 0))))
				{
				
					up[i % n] -=1;
					left[i / n] -=1;
					way[k+1] = i;
					f(i,k+1); 
					up[i % n] +=1;
					left[i / n] +=1; 
				}
				b[i] = 0;
			}
		}
	}
}
int main()
{
	int i;
	scanf("%d",&n);
	n2 = n*n;//
	for(i = 0; i < n;i++)
		scanf("%d",&up[i]);
	for(i = 0; i < n;i++)
		scanf("%d",&left[i]);
	up[0] -= 1;
	left[0] -= 1;
	f(0,0);
}
  1. 未名湖边的烦恼

问题描述

  每年冬天,北大未名湖上都是滑冰的好地方。北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩。

  每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个。现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)

输入格式

  两个整数,表示m和n

输出格式

  一个整数,表示队伍的排法的方案数。

样例输入

3 2

样例输出

5

数据规模和约定

  m,n∈[0,18]

#include<stdio.h>
int f(int m,int n){
	if(m<n){
		return 0;
	}
	else if(n==0){
		return 1;
	}
	else{
		return f(m-1,n)+f(m,n-1);
	}
}
int main(){
	int m,n;
	scanf("%d%d",&m,&n);
	printf("%d",f(m,n));
	return 0;
}

  1. 大臣的旅费

问题描述

很久以前,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最多花费的路费是多少。

样例输入1

5
1 2 2
1 3 1
2 4 5
2 5 4

样例输出1

135

输出格式

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

#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
ll INF = 1e12;
const int N = 100005;
 
int n, val, max_dis;
struct node{
    int v;
    long long dis;
    node(int _v,long long _dis){
        v = _v;
        dis = _dis;
    }
    bool operator < (const node& a) const{
        return dis > a.dis;
    }
    
};
int vis[N];
long long dist[N];
vector<node> mp[N];
 
int Dijkstra(int start)
{
    priority_queue<node> q;
 
    for(int i = 1; i <= n; i++)
    {
        dist[i] = INF;
        vis[i] = 0;
    }
 
    dist[start]= 0;
    q.push(node(start,0));
     
    while(!q.empty())
    {
        node N = q.top();
        q.pop();
        if(vis[N.v]) continue;
        vis[N.v] = 1;
         
        for(int i = 0; i < mp[N.v].size(); i++)
        {
            node nP = mp[N.v][i];
            int to = nP.v;
            int _dis = nP.dis;
             
            if(_dis + dist[N.v] < dist[to])
            {
                dist[to] = _dis + dist[N.v];
                q.push(node(to, dist[to]));              
            }
        }  
    }
     
    int v = 0;
    for(int i = 1; i <= n; i++)
    {
        if(dist[i] > v)
            v = dist[i];
    }
    return v;
}
 
int main()
{
    int x, y, st,d;
    val = max_dis = -1;
    long long sum;
    
    scanf("%d", &n);
    
    for(int i = 1; i <= n - 1; i++)
    {
        scanf("%d %d %d", &x, &y, &d);
        mp[x].push_back(node(y, d));
        mp[y].push_back(node(x, d));
    }
    Dijkstra(1);
    for(int i = 1; i <= n; i++)
    {
        if(dist[i]>val)
        {
            val = dist[i];
            st = i;
        }
    }
    val=0;
 
    Dijkstra(st);
     for(int i = 1; i <= n; i++)
    {
        if(dist[i]>val)
        {
            val = dist[i];
            st = i;
        }
    }
    sum=val;
    
    cout <<sum*(1+sum)/2+sum*10 << endl;
    
    return 0;
}
 
 
 
  1. 2n皇后问题

Description

给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后

和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两

个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。

Input

输入的第一行为一个整数n,表示棋盘的大小。

接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,

如果一个整数为0,表示对应的位置不可以放皇后。

Output

输出一个整数,表示总共有多少种放法。

Sample Input

No.1

4

1 1 1 1

1 1 1 1

1 1 1 1

1 1 1 1

No.2

4

1 0 1 1

1 1 1 1

1 1 1 1

1 1 1 1

Sample Output

No.1

2

No.2

0

#include <stdio.h>
int  a[10][10];
int bj[3][20]={0};
int bj1[3][20]={0};
int n;
int sum=0;
void f2(int x )
{int y;
if(x==n)sum++; 
     else 
     { for(y=0;y<n;y++)
       if(a[x][y]==1&&bj1[0][y]==0&&bj1[1][x+y]==0&&bj1[2][x-y+n]==0)
           {   a[x][y]=3;
            bj1[0][y]=bj1[1][x+y]=bj1[2][x-y+n]=1;
            f2(x+1);
            bj1[0][y]=bj1[1][x+y]=bj1[2][x-y+n]=0;
            a[x][y]=1;
           } 
     }
}
void f(int x )//放置白后 
{int y;
if(x==n)f2(0);//放置 黑后 
     else 
     { for(y=0;y<n;y++)
       if(a[x][y]==1&&bj[0][y]==0&&bj[1][x+y]==0&&bj[2][x-y+n]==0)//左右对角 列 和当前坐标都未被标记可放 
           {   a[x][y]=2;
            bj[0][y]=bj[1][x+y]=bj[2][x-y+n]=1; 
            f(x+1);
            bj[0][y]=bj[1][x+y]=bj[2][x-y+n]=0; 
            a[x][y]=1;
           } 
     }  
}
int main()
{
int i,j;
scanf("%d",&n);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
f(0);
printf("%ld\n",sum);
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值