四月假期欢乐赛 内部考试

A 推数

题目描述

何老板在玩一个推理游戏,但他遇到了一点麻烦,需要你帮忙!请根据A,B两幅图,推导出C图代表的数字!
lqx123123


输入格式

一个由大写字母’B’和’W’构成的10*10的矩阵,表示图C;其中’B’表示黑色方块,’W’白色方块


输出格式

一行,一个数字,表示推导出的C代表的数字。


样例输入

BWWWWWWWWW
WWWWWWBWWW
WWWWBWWWWW
BWWWWWWWWW
WWWBWWWWWW
WWWWWWWWBW
WWWWBWWWWW
WWBWWWWWWW
WWWWWBWWWW
WWWWWWWBWW


样例输出

0349314752


这题找规律,没办法。
发现不了规律就没办法了。。。。
自求多福吧
规律是:
从左向右数的第i-1个(奇数排)
从右向左数的第10-i个(偶数排)

下面代码:

#include<stdio.h>
using namespace std;
int i,j;char a[20];
int main(){
    for(i=1;i<=10;i++){
        scanf("%s",a+1);
        for(j=1;j<=10;j++)
        if(a[j]=='B')printf("%d",(i&1)?j-1:10-j);
    }
} 

B 体重

题目描述

近日,信竞班有人在散布谣言,说何老板体重超重,这有损何老板在同学们心中的完美形象,让何老板很是头疼。何老板还了解到,散布该谣言的人号称自己拥有最合适的体重,体重值位于所有人的正中间,何老板决心找出这个家伙。

信竞班有n名同学,编号1到n,已知每名同学的体重都不相同。何老板想知道,哪个同学的体重位于正中间。也就是如果将n名同学按体重由轻到重排序后,该名同学位于第(n+1)/2名,这名同学一定是谣言散布者。

但是同学们都不肯准确告诉何老板他的体重,何老板只好在暗中收集信息。

例如:n=5时,何老板搜集到了如下信息:

1号同学比2号同学轻

3号同学比4号同学轻  

1号同学比5号同学轻  

2号同学比4号同学轻  

根据上面的情报,虽然何老板不能准确得出哪个同学具有中间体重,但他可以肯定4号和1号不可能具有中间体重,因为,1、2、3比4轻,而2、4、5比1重,所以他可以排除到这两名同学。

写一个程序统计出目前我们最多能排除掉多少个同学。也就是确定有多少个同学肯定不会是中间体重。
1<=n<=100

1<=m<=5000


输入格式

第一行:两个整数n和m,其中n为奇数表示学生总数,m表示何老板搜集到的信息条数。

接下来的m行,每行两个整数x和y,表示x号同学比y号同学重。


输出格式

若干个整数,按从小到大的顺序输出不可能是中间重量的学生的编号。
若一个也找不出来,输出0。


样例输入

5 4
2 1
4 3
5 1
4 2


样例输出

1 4


比大小找floyd
它很简单
他很易懂
她很好写

a[i][j]表示i是否肯定的比j重
b[i][j]表示i是否肯定的比j轻

加起来算答案就行了

第一次交是以为可以取等qwq

下面代码:

#include<stdio.h>
using namespace std;
int in[101],out[101];
bool a[101][101],b[101][101];
int x,y,n,m;bool f;
int main(){
    scanf("%d%d",&n,&m);
    while(m--){
        scanf("%d%d",&x,&y);
        a[x][y]=1;b[y][x]=1;
    }
    for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++){
        a[i][j]|=a[i][k]&&a[k][j];
        b[i][j]|=b[i][k]&&b[k][j];
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(a[i][j])in[i]++;
            if(b[i][j])out[i]++;
        }
        if(in[i]>(n>>1)||out[i]>(n>>1))printf("%d ",i),f=1;
    }
    if(!f)puts("0");
}

C 采蘑菇

题目描述

最近,何老板玩一款名叫“采蘑菇”的有趣手机游戏。
游戏地图由水平放置的n块砖(编号1到n)构成,每一秒钟,每块砖上会新长出一些蘑菇,蘑菇的生命时间只有1秒钟,1秒钟后蘑菇就消失了。游戏玩家操控的游戏角色“马里奥”一开始位于第k块砖上,每一秒钟,马里奥有三种移动方式可以选择:
1.原地不动,并采摘该砖上的蘑菇;
2.移动到左边一块砖,并采摘该砖上的蘑菇;
3.移动到右边一块砖,并采摘该砖上的蘑菇;
游戏一共持续t秒钟,问马里奥最多能采集到多少颗蘑菇。

对于30%的数据 1<=n<=10, 1<=t<=5;
对于100%的数据 1<=n<=100, 1<=t<=1000 ,1<=每块砖上长出的蘑菇数<=10000

样例1说明:
第一秒由2号砖移动到1号砖,采3颗蘑菇
第二秒呆在1号砖不动,采2颗蘑菇
第三秒由1号砖移动到2号砖,采5颗蘑菇


输入格式

第一行,四个整数n,t,k,分别表示砖块的数量,游戏的持续时间和一开始马里奥所处的位置。
接下来一个t*n的整数矩阵,其中第i行描述第i秒钟的情况,第i行第j个数表示第i秒第j块砖上长出的蘑菇数。


输出格式

一行,一个整数,表示能够采摘到的最多蘑菇数。


样例输入

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


样例输出

10


啊!经典的数塔问题
可以类似的定义第0秒以减小代码复杂度

代码:

#include<stdio.h>
#include<iostream>
using namespace std;
int a[101][1001],f[105][1005];
int n,t,k,i,j;
int main(){
    scanf("%d%d%d",&n,&t,&k);
    for(j=1;j<=t;j++)
    for(i=1;i<=n;i++)
    scanf("%d",&a[i][j]);
    for(j=t;j>=0;j--)
    for(i=1;i<=n;i++)
    f[i][j]=max(f[i][j+1],max(f[i-1][j+1],f[i+1][j+1]))+a[i][j];
    printf("%d",f[k][0]);
}

D 采蘑菇

题目描述

又到了桃子成熟的季节,何老板的果园推出了摘桃子的活动。
何老板的果园有N棵桃树,编号1到N。果园里有M条单向小路,将一些桃树连接起来,其中第i条小路连接Ai和Bi两棵桃树。何老板为了盈利,费劲心机做了以下规定:
1.顾客一开始从第S号桃树开始摘桃活动;
2.每棵桃树上有无限多个桃子,但是顾客一次在一棵桃树上最多只能摘D个桃子,然后他必须到其它桃树去摘桃。当然,顾客也可以在其他地方摘桃后又回到原来摘过桃的桃树,再摘D个桃子。而且这样往返摘桃的次数是没有限制的
3.为方便顾客摘桃,何老板还提供电动车服务,电动车总共有T条单向线路,每条线路连接两棵桃树,其中第i条电动车线路连接Xi和Yi两棵桃树,乘坐一次的需要支付给何老板Vi个桃子。如果顾客手中没有桃子,也可以乘坐电动车,用以后摘取得桃子来支付就行;
4.顾客可以选在在任何时刻,任何桃树处结束他的摘桃活动;

今天你来到何老板的果园,你想知道,最多可以摘到多少个桃子呢?如果可以摘到无限度个桃子,输出”Poor boss he”
2 <= N <= 1000
1 <= M <= 1000
1 <= T <= 1000
1 <= D <= 1,000
1 <= Vi <= 50,000


输入格式

第一行,5个整数,分别是D,M,N,T,S
接下来M行,每行两个整数Ai和Bi,表示从Ai号桃树到第Bi号桃树有条单向小路
接下来T行,每行三个空格间隔的整数Xi,Yi,Vi,表示有一条从Xi号桃树到Yi号桃树的单向电动车线路,乘坐一次的花费为Vi个桃子


输出格式

一个整数,表示最多能摘到的桃子个数。
若个数无限,输出”Poor boss he”


样例输入

100 3 5 2 1
1 5
2 3
1 4
5 2 150
2 5 120


样例输出

250


一共有两种边
一种是M条单向小路,设定其边权为(-1)*D,表示没走(这条边)之前何老板会损失D个桃子
另一种是何老板提供的电动车服务,设定其边权为何老板还提供电动车服务Vi-D,表示没走(这条边)之前何老板会损失Vi-D个桃子
Poor boss he 的情况就是有负权回路
如果有解加上在结束点可以获得的桃子数及D个就行了。
最后打个句号会不会很突兀

代码:

#include<stdio.h>
#include<queue>
using namespace std;
const int N=1000; 
int st[N+1],ed[N*2+1],nxt[N*2+1],len[N+N+1],tot;
int n,m,d,t,s,x,y,z;
int dis[N+1],cnt[N+1];
bool v[N+1];
queue<int>q;
void ADD(int x,int y,int z){
    ++tot;
    nxt[tot]=st[x];
    st[x]=tot;ed[tot]=y;
    len[tot]=z;
}
void SPFA(int s){
    for(int i=1;i<=n;i++)dis[i]=1e9,v[i]=0;
    q.push(s);dis[s]=0;v[s]=cnt[s]=1;
    while(!q.empty()){
        int x=q.front();q.pop();v[x]=0;
        for(int l=st[x];l;l=nxt[l])
        if(dis[ed[l]]>len[l]+dis[x]){
            dis[ed[l]]=dis[x]+len[l];
            if(!v[ed[l]]){
                ++cnt[ed[l]];
                if(cnt[ed[l]]==n){
                    puts("Poor boss he");
                    return;
                }
                q.push(ed[l]);v[ed[l]]=1;
            }
        }
    }
    int ans=1e9;
    for(int i=1;i<=n;i++)ans=min(ans,dis[i]);
    printf("%d",-ans+d);
}
int main(){
    scanf("%d%d%d%d%d",&d,&m,&n,&t,&s);
    while(m--){
        scanf("%d%d",&x,&y);
        ADD(x,y,-d);
    }
    while(t--){
        scanf("%d%d%d",&x,&y,&z);
        ADD(x,y,z-d);
    }
    SPFA(s);
}

E 数列

题目描述

有X,Y两个整数数列,现在需要我们用最小的操作次数,将X数列转换成与Y相同的数列。
对于X数列,我们有以下三种操作:
1.删除一个数字;
2.插入一个数字;
3.将一个数字改为另一个数字;
请你计算出完成转换所需的最小操作数。

1<=n,m<=2000, 0<=数列中的数字<=1000

样例1说明:
第一步:将数字1修改为8
8 2 3 4 5 6 7
8 2 3 8 7
第二步:将数字4删掉
8 2 3 5 6 7
8 2 3 8 7
第三步:将数字5删掉
8 2 3 6 7
8 2 3 8 7
第四部:将数字6修改为8
8 2 3 8 7
8 2 3 8 7


输入格式

第一行,两个整数n和m,分别代表X,Y两个数列的长度。
第二行,n个空格间隔的整数,表示X数列
第三行,m个空格间隔的整数,表示Y数列


输出格式

一行,一个整数,表示最少所需的操作数。


样例输入

7 5
1 2 3 4 5 6 7
8 2 3 8 7


样例输出

4


又是动规。
不说了上:
f[i][j]表示使a的前i个,与b的前j个相等的操作次数
剩下的方程在代码里就不赘述了。

代码:

#include<stdio.h>
#include<iostream>
using namespace std;
int f[2005][2005],a[2005],b[2005];
int n,m,x,y,i,j;
int main(){
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    for(j=1;j<=m;j++)scanf("%d",&b[j]);
    for(i=0;i<=max(n,m);i++)f[0][i]=f[i][0]=i;
    for(i=1;i<=n;i++)
    for(j=1;j<=m;j++)
    if(a[i]==b[j])f[i][j]=f[i-1][j-1];
    else f[i][j]=min(f[i-1][j-1],min(f[i-1][j],f[i][j-1]))+1;
    printf("%d",f[n][m]);
}

四月假期欢乐赛题解到此结束!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值