纪中模拟赛——普及

第一题(手机):

一般的手机的键盘是这样的:
1 2abc 3def
4ghi 5jkl 6mno
7pqrs 8tuv 9wxyz

要按出英文字母就必须要按数字键多下。例如要按出 x 就得按 9 两下,第一下会出 w,而第二下会把 w 变成 x。 0 键按一下会出一个空格。
你的任务是读取若干句只包含英文小写字母和空格的句子,求出要在手机上打出这个句子至少需要按多少下键盘。

输入

输入文件只包含一行,表示一个句子,句子中只包含英文小写字母和空格,且不超过200 个字符。

输出

一行一个整数,表示按键盘的总次数。

样例输入

i have a dream

样例输出

23

数据范围限制

【数据范围】
不超过 200 个字符。

解题思路:

暴力模拟————

源程序:

#include <cstdio>
#include <cstring>
using namespace std;
char c;
int ans,i,n[27]={0,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4};//a,b,c……x,y,z等需要按得次数。
int main()
{
    /*freopen("mobile.in","r",stdin);
    freopen("mobile.out","w",stdout);*/ 
    while ((c=getchar())!='\n') //输入
     {
        if (c==' ') ans++;//空格+1
        else ans+=n[c-96]; //只有小写字母
     }
    printf("%d",ans);//输出
    return 0;
}

第二题(游戏):

Atlantis Island 沉没以前,传说中的猫老大和 King 是好朋友……King 很喜欢赌博,这次 King和老朋友猫老大多年不见, 于是便邀请猫老大来玩一个游戏,猫老大应邀参加了。 King 拿出了 n 块黄金(0

解题思路:

某大佬讲题:“数据这么大,要不找规律,要不特殊算法!”
那我们就来找找规律吧。
1时输出:MaoLaoDa will win.
        1

2时输出:MaoLaoDa will win.
        2

3时输出:King will win.

4时输出:MaoLaoDa will win.
        1

5时输出:MaoLaoDa will win.
        2

6时输出:King will win.

7时输出:MaoLaoDa will win.
        1

8时输出:MaoLaoDa will win.
        2

9时输出:King will win.
So,可以看出模3取余就可以算出————如果模3得0则King赢,否则是猫老大赢,而且先取模3得出的结果个黄金。
但是,数据这么大,怎么处理呢?记得小学学过的东西吗?怎么判断是否是3的倍数————每一位的数字和,如果是3的倍数,那么这个数就是三的倍数。

源程序:

#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
string c;//用字符数组会超时
int main()
{
    freopen("atlantis.in","r",stdin);
    freopen("atlantis.out","w",stdout);
    for (int i=1;i<=3;i++)
     {
        cin>>c;//scanf读入不了
        int ans=0;
        for (int j=0;j<c.size();j++)
         ans+=c[j]-48;//将这个数每位得数字相加
        if (ans%3==0) printf("King will win.\n");//判断
        else printf("MaoLaoDa will win.\n%d\n",ans%3);//判断
     }
}

第三题(家族):

在一个与世隔绝的岛屿上,有一个有趣的现象:同一个家族的人家总是相邻的(这里的相邻是指东南西北四个方向),不同的家族之间总会有河流或是山丘隔绝,但同一个家族的人不一定有相同姓氏。现在给你岛上的地图,求出岛上有多少个不同的家族。岛上的地图有n 行,每行有若干列,每个格子中要么是’空格表示大海,要么是‘ *’,表示河流或山丘,要么是小写字母,表示一户人家的姓氏。

输入

第一行是个数字 N,表示下面信息的行数,接下来是 N 行字符,每行由小写字母和*号组成,有些行的最前面也可能包含若干连续的空格,表示这些区域是大海,每一行最多不超过 200 个字符。

输出

一个数字,表示家族数。

样例输入

4
*zlw**pxh
l*zlwk*hx*
w*tyy**yyy
zzl

样例输出

3

数据范围限制

【数据范围】
10%的数据, n<=1
30%的数据, n<=10
100% 的数据, n<=100 每一行最多不超过 200 个字符

解题思路:

这题数据比较弱,bfs(广搜)和dfs(深搜)都可以。我用得是广搜(快嘛!)。

源程序:

#include <cstdio>
using namespace std;
char c;
int ans,o,n,a[101][201],dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1},father[20001],state[20001][3];
void bfs(int x,int y)//广搜
{  
    int p,head=0,tail=1;
    a[x][y]=0;state[1][1]=x;state[1][2]=y;
    do  
    {  
        head++;  
        for (int i=1;i<=4;i++)  
         {  
            int x=state[head][1]+dx[i];  
            int y=state[head][2]+dy[i];  
            if (x>0&&y>0&&x<=n&&y<=o&&a[x][y]) //每找到一个连在一起的家
            {  
                tail++;
                father[tail]=head;  
                state[tail][1]=x;  
                state[tail][2]=y;  
                a[x][y]=0; //就把它变成河(山)流(丘),以免重复
            }  
         }  
    }
    while(head<tail);  
}  
int main()
{
    //freopen("family.in","r",stdin);
    //freopen("family.out","w",stdout);
    scanf("%d",&n); //一开始就卡着,没打\n,后来补上,发现————还是错的
    for (int i=0;i<=n;i++)//So我就把1..n改为0..n
     {
        o=0;
        while((c=getchar())!='\n')
         {
            o++;
            if (c>='a'&&c<='z')
            a[i][o]=1;  else a[i][o]=0;
         }
     } //接着一系列读入
    o=200; //把每一行读入得字符长度变得相同(应该比较好做)
    for (int i=1;i<=n;i++)  
     for (int j=1;j<=o;j++)  
        if (a[i][j]) //如果不是河(山)(海)流(丘),就来一次bfs
        {  
            bfs(i,j);//bfs不解释
            ans++;//连在一起的家族  总数+1
        } 
    printf("%d",ans);//输出
}

第四题(作业):

光光上了高中,科目增多了。在长假里,光光的老师们都非常严厉,都给他布置了一定量的作业。假期里,光光一共有的时间是 k 小时。在长假前,老师们一共给光光布置了 n份作业,第 i 份作业需要的时间是 ti 小时。但是由于老师们互相不商量,因此光光有可能不能完成老师的作业。当可能不能完成老师的作业时,光光就事后去向老师说明,然后被老师批评一顿了事。对于一件作业,只有 2 种情况:完成或者不完成(快要完成也算不完成)。
如果没完成,受到批评是天经地义的。但是,不同的作业对于光光来说,批评的力度是不同的。第 i 件作业如果没完成,就要受到 pi 个单位的批评。多次这样之后,光光想要在长假前就知道他至少会受到多少个单位的批评。你能帮助他吗?

输入

输入文件的第一行只有一个数字 k。
第二行只有一个数字 n。
接下来 n 行,每行两个数字,分别是 ti 和 pi,两个数字之间用一个空格分开。

输出

输出文件 homework.out 仅包含一行,是一个数字,代表了光光最少受到的批评。

样例输入

5
3
2 6
1 3
4 7

样例输出

6

数据范围限制

【数据范围】
100%的数据中, k<=100000, ti<=10000, pi<=10000;
30%的数据中, n<=20;
100%的数据中, n<=500。

解题思路:

数据也不大,普通的01背包。

动态转移方程:f[v]=max(f[v-w[i]]+c[i],f[v]);

源程序:

#include<cstdio>  
using namespace std;  
int n,m,ans,f[100001],w[501],c[501];
int max(int x,int y)//max函数不解释
{  
    return x>y?x:y;  
}  
int main()  
{
    freopen("homework.in","r",stdin);
    freopen("homework.out","w",stdout); 
    scanf("%d%d",&m,&n);
    for (int i=1;i<=n;i++)  
     {
        scanf("%d%d",&w[i],&c[i]);//w表示要用的时间,c表示(没)做完(可以)免(受)掉(到)的批评
        ans+=c[i];//先把所有加起来,作用————后面再说
     }
    for (int i=1;i<=n;i++)  
     for (int v=m;v>=w[i];v--)
      f[v]=max(f[v-w[i]]+c[i],f[v]);//就是01背包————不懂得————没办法
    printf("%d",ans-f[m]);//用批评总量减去写完的科目的批评总量,得出结果
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值