您的位置:首页 > 其它

纪中训练 day2 【NOIP普及组】模拟赛D组 解题报告

2018-01-26 16:45 393 查看

☞第一题 手机☜

大意

用九键手机打一串字符的按键次数。

思路

利用map库,以字符为坐标,然后一一对应,输出。

代码

#include<cstdio>
#include<string>
#include<map>//STL打发好
using namespace std;
map<char,int>m;int ans;char c;
int main()
{
freopen("mobile.in","r",stdin);
freopen("mobile.out","w",stdout);
m['*']=m['#']=m[' ']=1;
m['a']=m['d']=m['g']=m['j']=m['m']=m['p']=m['t']=m['w']=1;
m['b']=m['e']=m['h']=m['k']=m['n']=m['q']=m['u']=m['x']=2;
m['c']=m['f']=m['i']=m['l']=m['o']=m['r']=m['v']=m['y']=3;
m['s']=m['z']=4;//优雅的打表
while((c=getchar())!=EOF)
ans+=m[c];
printf("%d",ans);//输出
}

☞第二题 游戏☜

大意

有n<=10^100002次方块黄金,两人轮流取黄金,一次只能取2的次方的正整数个数(包括1),由其中一个人先取,问最后谁能赢,如果先取的人赢了,第一次最少拿几块。

思路

这题数据那么大,一定是找规律类型的,所以我们先把规律找出来。
1 2 3 4 5 6 7 8 9
1 2 0 1 2 0 1 2 0 (0表示后出手拿的那个赢)
然后,我们发现,是三的倍数就是后出手的赢,否则反之,第一次最少取的就是mod 3 的余数。
但是这个数很大,怎么办呢?利用三的倍数的思想,把各个位数的和算出来,最后%3就可以了。

代码

#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<ios
4000
tream>
#define hh endl
using namespace std;
int c;string s,mld="MaoLaoDa will win.",kin="King will win.";
int main()
{
freopen("atlantis.in","r",stdin);
freopen("atlantis.out","w",stdout);
srand(time(NULL));//之前蒙题用的,见谅。。。
for (int i=1;i<=3;i++)
{
c=0;
cin>>s;for(int j=0;j<s.size();j++) c+=s[j]-48;//求和
if(c%3) cout<<mld<<hh<<c%3<<hh;else cout<<kin<<hh;//判断,输出
}
}

☞第三题 家族☜

大意

有一个n*m的矩阵(m未知,n<=100,m<=200),之间有障碍,如果四周没有障碍就说这两个点是一个家族的,求家族数

思路

利用深搜(广搜皆可)的思想遍历一遍,对于输入,用getchar,因为它说空格也是障碍,所以用getchar。
对于越界的问题,我们多开一个数组len,来存长度,就可以避免越界了。

代码

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char g;
bool b[101][201];
int n,len[101],ans;
void dfs(int x,int y)//深搜
{
if(!b[x][y]||x<1||y<1||x>n||y>len[x]) return;//判断
b[x][y]=0;//标记
dfs(x+1,y);dfs(x,y+1);dfs(x-1,y);dfs(x,y-1);//继续搜
}
int main()
{
freopen("family.in","r",stdin);
freopen("family.out","w",stdout);
scanf("%d",&n);
for(int i=0;i<=n;i++)
while((g=getchar())!='\n')
b[i][++len[i]]=g>='a'&&g<='z';//输入
for(int i=1;i<=n;i++)
for(int j=1;j<=len[i];j++)
if (b[i][j]){dfs(i,j);ans++;}//如果没有障碍,就说明又有一个新家族
printf("%d",ans);//输出
}

☞第四题 作业☜

大意

有k<=100000点时间,n<=500项作业,每项作业可做可不做,不做作业有一定的惩罚值,求最小值。

思路

求最小惩罚值,其实就是求最大减免惩罚值,我们把惩罚看做价值,也就是做这项作业可以减免多少惩罚,求之最大值。再用所有惩罚的总和减去最大减免值即为最优解。。。

代码

#include<cstdio>
using namespace std;
int f[100001],n,m,w,p,ans;
int max(int x,int y){return x>y?x:y;}
int main()
{
freopen("homework.in","r",stdin);
freopen("homework.out","w",stdout);
scanf("%d\n%d",&m,&n);
for (int i=1;i<=n;i++)
{
scanf("%d %d",&w,&p);ans+=p;//累加
for(int j=m;j>=w;j--)//其实两个可以一起,这样就省掉了两个数组
f[j]=max(f[j],f[j-w]+p);
}
printf("%d",ans-f[m]);//输出
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: