您的位置:首页 > 其它

纪中模拟赛——普及

2018-01-26 19:38 176 查看

第一题(手机):

一般的手机的键盘是这样的:

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++)

4000
{
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: