第四届图灵杯程序设计竞赛

第四届“图灵杯”NEUQ-ACM程序设计竞赛(个人赛)

                                                                                                             2016-11-19

问题 A: 蔡老板的会议

时间限制: 2 Sec   内存限制: 128 MB
提交: 223   解决: 19
[ 提交][ 状态][ 讨论版]

题目描述

图灵杯个人赛就要开始了,蔡老板召集俱乐部各部门的部长开会。综合楼有N (1<=N<=1000)间办公室,编号1~N每个办公室有一个部长在工(mo)作(yu),其中X号是蔡老板的办公室,会议也将在X(1<=X<=N)号办公室举行。综合楼的构造极其特殊,这N个办公室之间M(1<=M<=100,000)条单向走廊。通过第i条路将需要花费Ti(1<=Ti<=100)单位时间。
由于工作很忙,开完会之后各部长需要返回自己的办公室。他们会选择最短时间的最优路径。
为了合理安排接下来的工作,蔡老板想知道,【来回最久的】【!!!】那个部长在路上花费的时间是多少。

输入

第一行:用空格隔开的三个数N,M和X
接下来的M行:每行有用空格隔开的三个数Ai,Bi和Ti,表示从A点到B点花费的时间Ti

输出

一个int型的数,表示花费时间的最大值

样例输入

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

样例输出

8

这是在最短路里面找到最长的那条,再求X到最长的那个点的距离。其实就是最短路。

#include 
#include
#include
#define siz 1005
#define inf 9999999
using namespace std;
long long int gx[siz][siz],gy[siz][siz];
long long int dx[siz],dy[siz];
int vis[siz];
int n,m,x;
int main()
{
    int a,b,t;
    while(scanf("%d %d %d",&n,&m,&x)!=EOF)
    {
        memset(vis,0,sizeof(vis));
        for(int i=1; i<=n; i++){
            for(int j=1; j<=n; j++)
                gx[i][j]=gy[i][j]=inf;
            //gx[i][i]=gy[i][i]=0;
        }
        for(int i=1;i<=m;i++){
            scanf("%d %d %d",&a,&b,&t);
            if(gx[a][b]>t) gx[a][b]=t;
            if(gy[b][a]>t) gy[b][a]=t;
        }
 
        for(int i=1;i<=n;i++) dx[i]=gx[x][i];
        vis[x]=1, dx[x]=0;
        while(1){
            int v=-1,mx=inf;
            for(int i=1;i<=n;i++)
            {
                if(!vis[i]&&dx[i]dx[v]+gx[v][i])
                    dx[i]=dx[v]+gx[v][i];
            }
        }
        ///--------------------------
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++) dy[i]=gy[x][i];
        vis[x]=1, dy[x]=0;
        while(1){
            int v=-1, mx=inf;
            for(int i=1;i<=n;i++)
            {
                if(!vis[i]&&dy[i]gy[v][i]+dy[v])
                    dy[i]=gy[v][i]+dy[v];
            }
        }
        int ans=-9999;
        for(int i=1;i<=n;i++)
        {
            if(ans

问题 B: 一个简单的问题

时间限制: 1 Sec   内存限制: 128 MB
提交: 1226   解决: 174
[ 提交][ 状态][ 讨论版]

题目描述

这是一个三层的字母塔。

如何输出一个任意层数的字母塔呢?

输入

一个数字n(1<=n<=26),表示字母塔的层数

输出

n层的字母塔

样例输入

4

样例输出

   A
  ABA
 ABCBA
ABCDCBA

这是一道水题,跟以前做过的打印三角形一样,用for 循环做

#include 
#include
#include
#include
#define siz 500000
using namespace std;
 
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0; i=0; k--)
                printf("%c",'A'+k);
            printf("\n");
        }
    }
 
    return 0;
}

问题 C: 粉丝与汉诺塔

时间限制: 1 Sec  内存限制: 128 MB
提交: 321  解决: 122
[ 提交][ 状态][ 讨论版]

题目描述

苟利国家生死以,岂因福祸避趋之?作为ACM真正的粉丝,应该都听闻过汉诺塔问题,汉诺塔问题是这样的:

         有三根柱子,编号A,B,C柱,初始情况下A柱上有n个盘子,小盘子在上大盘子在下,n个盘子大小各不一样,每次移动一个最上层的盘子算作一步,大盘子无法移动到小盘子上面,现在要把n个盘子从A柱全部移动到C柱,请问一共需要多少步?

现在对汉诺塔问题加以限制,每次移动只能经由中间柱实现,即是说如果想从A柱移动到C柱,只能A到B,然后B到C这样移动,反之亦然,那么请问,n个盘子从A柱全部移动到C柱一共需要多少步?

输入

多组输入,每组输入一个正整数n(1<=n<=18)

输出

每行输出一个正整数答案

样例输入

12

样例输出

2

这个题有点坑,16以上就要用打表的方法做,不然递归会超时。

#include 
#include 
 
using namespace std;
 
int a[19];
int ans;
 
void hanoi(int n,char one,char two,char three)
{
    if(n==1) ans+=2;
    else
    {
        hanoi(n-1,one,two,two);
        ans++;
        hanoi(n-1,two,two,three);
        ans++;
        hanoi(n-1,one,two,three);
    }
}
 
 
int main()
{
    int n;
    a[15]=14348906;
    a[16]=43046720;
    a[17]=129140162;
    a[18]=387420488;
    while(scanf("%d",&n)!=EOF)
    {
        ans=0;
        if(n>=15){
            printf("%d\n",a[n]);
            continue;
        }
 
        hanoi(n,'A','B','C');
        printf("%d\n",ans);
    }
 
    return 0;
}

问题 D: 拿糖果

时间限制: 1 Sec   内存限制: 128 MB
提交: 383   解决: 44
[ 提交][ 状态][ 讨论版]

题目描述

薯片和他的朋友薯条来到了商店,商店有n个糖果,标号依次为1,2,3....n,对应的价值为W1,W2,W3...Wn。现在薯片先拿走一个标号为a的糖果,标号小于a的糖果就被商家收回去了,然后薯条只能在剩下的糖果中选一个标号为b的糖果,请问Wa-Wb的最大值是多少?

输入

多组数据输入,每一组数据第一行输入一个数字 n(2<=n<=100000),接下来n行,每行输入一个wi表示第i个糖果的价值(0

输出

每组数据输出Wa-Wb的最大值

样例输入

3
3 2 1
6
1 1 1 1 1 1

样例输出

2

这个题可以用DP的思想。不多说,上代码。

#include 
#include 
#include 
#define N 100005
#define inf 0x3f3f3f
using namespace std;
int p[N];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        memset(p,0,sizeof(p));
        int i;
        for(i=0;i_){
                    _=wb;
                }
            }
            else if(p[i]>=wa){
                wb=wa-p[i];
                if(wb>_){
                    _=wb;
                }
                wa=p[i];
            }
        }
        printf("%d\n",_);
    }
    return 0;
}

问题 E: 粉丝与分割平面

时间限制: 1 Sec   内存限制: 128 MB
提交: 234   解决: 75
[ 提交][ 状态][ 讨论版]

题目描述

在一个平面上使用一条直线最多可以将一个平面分割成两个平面,而使用两条直线最多可将平面分割成四份,使用三条直线可将平面分割成七份……这是个经典的平面分割问题,但是too simple,作为一个可以对困难谈笑风生的人,我们现在将问题改一下,不再使用平面,而使用一个角来分割平面,一个角最多可以将平面分成两份,两个角最多可以将平面分成七份……那么n个角可以将平面分割成几个部分呢?再进一步,考虑用圆可以将平面分割成几部分呢?聪明的你肯定想得到,答案是

输入

第一行一个正整数T1<=T<=20)表示测试数据的数量,之后每行两个正整数nm1<=n,m<=1000)分别表示使用n个角和m个圆。

输出

每组数据输出两个答案s1s2,分别表示使用n个角可将平面分割成s1份,使用m个圆可将平面分割成s2

样例输入

2
1 1
2 3

样例输出

2 2
7 8

这个题知道公式就很好办。给个链接 点击打开链接

链接里面有很详细的平面分割问题。

#include 
#include 
using namespace std;
 
int main (){
    int n;
    int sq=0,cir=0,sqn,cirn;
    cin>>n;
    while(n--){
        cin>>sqn>>cirn;
        sq=2*sqn*sqn-sqn+1;
        cir=2+cirn*(cirn-1);
        cout<


F题写不出,Orz。


问题 G: 爬楼梯

时间限制: 1 Sec   内存限制: 128 MB
提交: 153   解决: 51
[ 提交][ 状态][ 讨论版]

题目描述

由于第m个台阶上有好吃的薯条,所以薯片现在要爬一段m阶的楼梯.
薯片每步最多能爬k个阶梯,但是每到了第i个台阶,薯片身上的糖果都会掉落ai个,现在问你薯片至少得掉多少糖果才能得到薯条?

输入

多组数据输入,每组数据第一行输入两个数字m(1

输出

对于每组数据,输出至少要牺牲的糖果数.

样例输入

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

样例输出

9
9

这是个动态规划题。

#include 
#include
#include
#define siz 1005
using namespace std;
int n,k,q[siz],a[siz],d[siz];
int main()
{
    int f,b;
    while(scanf("%d %d",&n,&k)!=EOF)
    {
        memset(d,0,sizeof(d));
        memset(q,0,sizeof(q));
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        q[1]=0;
        f=b=0;
        d[0]=0;
        for(int i=1;i<=n;i++)
        {
            int u;
            u=q[b];
            d[i]=d[q[f]]+a[i];
            while(d[u]>d[i]&&f<=b){
                b--;
                u=q[b];
            }
            q[++b]=i;
            if(q[f]



问题 H: 吃薯条

时间限制: 1 Sec   内存限制: 128 MB
提交: 465   解决: 105
[ 提交][ 状态][ 讨论版]

题目描述

薯片这次又遇到问题了==
薯片有n个薯条棒,第i个薯条棒的长度为i,由于薯片能瞬间移动,所以薯片能在1秒内从这n个薯条棒里面选择一个或者多个,吃掉同样长的一部分,
并且被吃掉部分的长度是正整数,问薯片至少多少时间能把这n个薯条棒都吃完?

输入

多组数据输入,每组数据第一行输入一个n(1<=n<=109).

输出

对于每组数据,输出最短的时间.

样例输入

3
4

样例输出

2
3

这个题是找规律的题目,我是自己手动找规律的。


#include 
#include 
#include 
 
using namespace std;
 
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int t=0;
        while(n>0)
        {
            if(n%2!=0)
                n=n-(n/2+1);
            else
                n=n-n/2;
            t++;
        }
        printf("%d\n",t);
    }
    return 0;
}

东北大学的链接,感觉界面挺好的,代码查重也是妥妥的。

NEUQACM OJ


你可能感兴趣的:(OJ题解)