NENU 17级算法学习小组Round 3 0606

题目链接

密码:12345678

A题:非常简单。不过容易PE,需要注意空格和空行的输出,用printf输入的时候需要注意getchar()的使用。

#include <iostream>
using namespace std;
int main()
{
    int n, flag=0;
    char c;
    while(cin>>c&&c!='@'){
        cin>>n;
        if(flag!=0) cout<<endl;
        for(int i=0; i<n-1; i++){
            for(int j=n-i-2; j>=0; j--)
                cout<<" ";
            cout << c;
            if(i==0) cout<<endl;
            else{
                for(int k=i*2-2; k>=0; k--)
                    cout<<" ";
                cout << c << endl;
            }
        }
         for(int i=0; i<2*n-1; i++)
                cout<<c;
            cout<<endl;
        flag = 1;
        //cout<<"exo me"<<endl;
    }
    return 0;
}

下边是组测试数据,注意行末没有空格。

B题:找规律题。打表,就是提前算好,有多组测试数据的时候,效率比较高。

#include <stdio.h>
#define MAXN 50
typedef unsigned long long ULL;
ULL fn[MAXN+1];
void setfn()
{
    int i;
    fn[0] = 0;
    fn[1] = 0;
    fn[2] = 1;
    fn[3] = 2;
    for(i=4; i<=MAXN; i++)
        fn[i] = fn[i-2] + fn[i-1];
}
int main(void)
{
    int n, a, b;
    // 先打表(以防万一测试集合大)
    setfn();
    scanf("%d", &n);
    while(n--) {
        // 读入a和b
        scanf("%d%d", &a, &b);
        // 输出结果
        printf("%lld\n", fn[b - a + 1]);
    }
    return 0;
}

C题:题意:判断一个字符串是不是回文串。

    思路:只需要对这个串从起始位置和末尾位置比较一下,一个for循环就行了。

#include <iostream>
#include <string>
using namespace std;
int main()
{
	int n,i;
	string s;
	cin>>n;
	while (n--) 
	{
		cin>>s;
		bool flag = true;
		for (i = 0; i < s.size()/2; i++) 
			{
				if(s[i] != s[s.size() - i - 1])
				{
					flag = false;
					break;
				}
			}
		if(flag) 
			cout<<"yes"<<endl;
		else 
			cout<<"no"<<endl;
	}
	return 0;
}

D题:最短路问题。实际上这个题几乎就是把离散老师上课讲的Dijkstra最短路翻译一下偷笑其实只听老师上课讲,应该能懂Dijkstra算法,但你会觉得代码不好实现,而这道题就是教你用Dijkstra算法编程解决最短路问题。(这道题询问的是单源最短路,而Dijkstra也只能解决单源最短路问题,那么如过遇到多源最短路问题该怎么做呢?还有一种解决最短路问题的算法,floyd算法,有兴趣的同学可以了解一下,下边这个链接讲的比较好,代码也容易实现。有些单源最短路问题也能用floyd来写,但是容易超时,对于这个题,用floyd就会超时。只有五行的floyd最短路算法

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define inff 1000010
#define maxn 100010
using namespace std;
int e[10100][10100];
int main()
{
    int dis[201000],book[201000],i,j,n,m,t1,t2,t3,u,v,min;
    int inf=99999999; //用inf(infinity的缩写)存储一个我们认为的正无穷值
    //读入n和m,n表示边数,m表示顶点数
    scanf("%d %d",&n,&m);

    //初始化
    for(i=1;i<=m;i++)        //注意是从1到m还是从0到m-1,要看题目怎样输入的
        for(j=1;j<=m;j++)
            if(i==j) e[i][j]=0;
              else e[i][j]=inf;

    //读入边
    for(i=1;i<=n;i++)
    {
        scanf("%d %d %d",&t1,&t2,&t3);
        if(t3<e[t1][t2])     //连个两点之间有多条,要判断哪个边更小,取较小的边
            e[t1][t2]=e[t2][t1]=t3;//这是一个无向图,所以两面都要更新
    }
    //初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
    for(i=1;i<=m;i++)
        dis[i]=e[1][i];
    //book数组初始化
    for(i=1;i<=m;i++)
        book[i]=0;
    book[1]=1;

    //Dijkstra算法核心语句
    for(i=1;i<=m-1;i++)
    {
        //找到离1号顶点最近的顶点
        min=inf;
        for(j=1;j<=m;j++)
        {
            if(book[j]==0 && dis[j]<min)
            {
                min=dis[j];
                u=j;
            }
        }
        book[u]=1;
        for(v=1;v<=m;v++)
        {
            if(e[u][v]<inf)    //可以不要
            {
                if(dis[v]>dis[u]+e[u][v])
                    dis[v]=dis[u]+e[u][v];
            }
        }
    }
    cout<<dis[m]<<endl;
    return 0;
}

E题:递推即可(也可以打表)。

#include <stdio.h>
// 递推式 f(n) = n n<=4,f(n) = f(n-1) + f(n-3) n>4
int cow(int n)
{
    if(n <= 4)
        return n;
    else
        return cow(n-1) + cow(n-3);
}
int main(void)
{
    int n;
    while(scanf("%d", &n) != EOF) {
        // 判定结束条件
        if(n == 0)
            break;
        // 计算并输出结果
        printf("%d\n", cow(n));
    }
    return 0;
}

F题:非常简单的题目,直接上代码。sort函数用起来很方便啊得意(起码写起来很方便)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 1000010
#define maxn 10010
#define ll long long
using namespace std;
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
            break;
        int a[110];
        for(int i=0;i<n;i++)
            cin>>a[i];
        a[n]=m;
        sort(a,a+n+1);
        for(int i=0;i<n;i++)
            cout<<a[i]<<" ";
        cout<<a[n];
        cout<<endl;
    }
    return 0;
}

G题:题意:输入一个正整数n,输出第n个偶数长度的回文数字。

        思路:找规律题。写出前几项即可发现规律,第n个偶数长度的回文数字就是将n和“倒序”的n组合而成的,所以这题只 需要输出n,然后倒序输出n就行了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define inf 100000010
#define maxn 100010
using namespace std;
int main()
{
    char a[110000];
    cin>>a;
    char b[110000];
    int len=strlen(a);
    for(int i=0;i<len;i++)
    {
        b[len-i-1]=a[i];
    }
    cout<<a<<b<<endl;
    return 0;
}

H题:看似简单,但实际上需要考虑多种情况。首先,没说数据范围,那么数据范围就会有非常大(爆long long)的情况,所以要用数组存;其次,要考虑0的位置,前导零,小数点末尾的0,把它们都删掉,再用strcmp函数比较一下两个字符串是否相同就行了。(这道题的数据比较水,它没有考虑前导零的情况,所以有些同学如果没考虑前导零也能过,下边的代码是考虑了前导零的情况)

#include <cstdio>
#include <cstring>
char a[100017], b[100017];
void re1(char s[])    //去除前导零
{

    int k=0;
    int len=strlen(s);
    for(int i=0;i<len;i++)
    {
        if(s[i]!='0')
            {k=i;break;}
    }
    for(int i=k;i<len;i++)
        s[i-k]=s[i];
    //printf("##%d\n",k);
}
void re2(char s[])     //去除小数点后末尾的0 
{
    int len = strlen(s);
    int p = 0;
    for(int i = 0; i < len; i++)
    {
        if(s[i] == '.')
        {
            p = 1;
            break;
        }
    }
    if(p)
    {
        for(int i = len-1; i >= 0; i--)
        {
            if(s[i] == '0')
                s[i] = '\0';
            else
                break;
            len--;
        }
        if(s[len-1] == '.')
            s[len-1] = '\0';
    }
}
int main()
{
    while(~scanf("%s%s",a,b))
    {
        re1(a);
        re2(a);
        //printf("**%s\n",a);//输出中间的量,debug
        re1(b);
        re2(b);
        //printf("&&%s\n",b);
        if(strcmp(a,b))
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/flyzer/article/details/80561644