第6次模拟赛题解

T1:

酸的命名(acid.cpp)

题目描述

         化学于光羽而言简直是一个噩梦!请你帮他分辨这两种酸: polyatomicnon-metal

  1. 用字符串表示一种化学用品,如果它的开头是hydro且结尾是ic那么就是non-metal
  2. 如果仅仅结尾是ic那么就是polyatomic
  3. 不满足以上两个条件,他就是not an acid

格式

         输入第一行,一个数q,表示询问个数。接下来q行,每行一个字符串描述化学用品。

         输出一共q行,每行为non-metal acid或polyatomic acid或not an acid

范围

        q <= 100

        2 <= 字符串长度 <= 10000

 

没有什么算法,只要稍微加一些判断

程序如下:

#include
using namespace std;
int main()
{
	freopen("acid.in","r",stdin);
	freopen("acid.out","w",stdout);
	int n;
	string s="hydro";
	char ch[10005];
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
        scanf("%s",&ch);
        int len=strlen(ch);
        if (ch[len-1]=='c'&&ch[len-2]=='i')  //结尾为 ic 
        {
        	int f=1;
        	for (int j=0;j<5;j++)
			 if (ch[j]!=s[j]) {f=0;break;}   //判断是不是 non-metal acid 
			if (f==1) cout<<"non-metal acid"; //如果是则输出 non-metal acid 
			if (f==0) cout<<"polyatomic acid"; //不是则输出 polyatomic acid
        }
        else cout<<"not an acid"; //不是酸 
        cout<

T2:

开锁大师(lock.cpp)

题目描述

         开锁大师光羽上线了!!!

         现在有n扇门,开始时,每扇门可能是开着也可能是关着的。大师的目标是把这些门都给打开。

         每次大师可以选择一扇关着的门,把它打开。如果这扇门右边有门且它是关着的,大师会顺便把它一起打开。

         请问,大师打开所有门,最少几次以及最多需要几次。

格式

         输入第一行一个数n,第二行n个数,每个数是0或者1,1表示这扇门锁着,0表示开着。

         输出两个数,表示最少和最多几次。

范围

         N <= 10000

Sample Input                                                                                       

10
0 1 1 0 1 1 1 1 0 0

Sample Output

3 6

 

设当前门的状况为x

得知最大数即为有多少门是关着的

证明:

   最坏的情况则是从最左边的关闭的们开始,由于是最左边关闭的门,所以它不存在 [右边的关着的门] ,所以max=关门数

实现:if (x==1) max++;

   得知最小数即为有多少扇门可以连续开

证明:

   最好的情况是有多道门可以连续开

实现:设当前连续的闭门数为 f 

    if (f%2==1) min++;    min+=f/2;

#include
using namespace std;
int main()
{
	freopen("lock.in","r",stdin);
	freopen("lock.out","w",stdout);
	int n,min=0,max=0,f=0,x;
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
    	scanf("%d",&x);
    	if (x==1) {max++;f++;}    //门关着时:最大值+1,连续段+1 
    	if (x==0)
    	{
    		if (f%2==1) min++;   //公式 
			min+=f/2;
			f=0;
    	}
    }
    if (f%2==1) min++;  //如果结尾有一段关着的门就不会被扫描到,因此要多一次操作 
	min+=f/2;
	printf("%d %d",min,max);
}

T3:

 

Problem 1 数学题(math.cpp/c/pas)

【题目描述】

给出一个n个未知数的方程,x[1],x[2],x[3]......x[n]

求x[1]+x[2]+x[3]....+x[n]==S的正整数解的个数,并且要保证,

对于任意i (1<=i< n) x[i]与x[i+1]相差不大于P;

【输入格式】

输入文件math.in

第一行三个整数n,S,P。

【输出格式】

输出文件math.out

一行一个整数表示方程解的个数。

【样例输入】

2 10 2

【样例输出】

3

【样例解释】

三种情况分别是:

5+5=10

4+6=10

6+4=10

【数据范围】

对于 30% 数据 2<=n<=10 ,p=0,S<=30;

对于 100% 数据 2<=n<=10,p<=3 , S<=30;

保证数据有梯度。

 

主体思想就是枚举每一个可能存在的 [初始值] ,然后判断相邻两个之间的差是否小于P,和是否等于S。

其实因为我们是从前到后一个一个搜索变量的值的,所以,每一个数的范围已经由上一个数的值确定了。所以这样搜索的状态就比较少了。

 

#include
using namespace std;
int s,n,p,t,a[100];
void dfs(int k,int x,int y)  //k为当前搜到了k个数
                             //x为当前搜到的值的和
							 //y为上一个值(缩小搜索范围) 
{
	if (x==s&&k==n) t++;  //满足条件 
	if (x>=s||k==n) return;
	for (int i=max(y-p,1);i<=min(s,y+p);i++)  //确定较为精准的范围 
	  dfs(k+1,x+i,i);   //搜索 
}
int main()
{
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
    scanf("%d%d%d",&n,&s,&p);
    for (int j=1;j<=s;j++) dfs(1,j,j);
	printf("%d",t);
}

 

T4:

农夫 John 正在研究他的农场的卫星照片.照片为一个R (1 <=

R <= 75) 行  C (1 <= C <= 75) 列的字符矩阵表示.如下图:

..................

..#####.......##..

..#####......##...

..................

#.......###.....#.

#.....#####.......     

图上的一块相连通的 "#" 表示一群奶牛或一个房间, 两个子"#" 连通的意思是说左右或上下相连.而下面的两块则是分开的:

....

.#..

..#.

....

John现在根据卫星照片上的的这些"#"块的形状来判断哪些是牛群,哪些是房间.如果一个"#"块形状的边是水平或垂直的矩形,则是房间.其它的则认为都是牛群.在第一个图中,有三个房间 ( 2x1, 2x5, and 1x1)和2群牛.

请根据输入文件中的数据,统计出房间数和牛群数.

数据中牛群不会包围另一个牛群或房间.

输入格式: satel.in

* 第一行,两个整数: R 和 C.

* 和 2..R+1行: 第 i+1 行表示照片的第 i 行情况,由 C 字符组成.

输出格式:

* 第一行: 房间数.

* 第二行: 牛群数.

输入样例 (file satel.in):

5 8

#####..#

#####.##

......#.

.###...#

.###..##

输出样例 (file satel.out):

2

2

 

我的思路是先搜索出每一块牛或者房子,由于 [数据中牛群不会包围另一个牛群或房间] ,所以可以找出每一块区域的起点(mina,minb)和末尾(maxa,maxb),由于房子的格子数是等于(maxa-mina+1)*(maxb-minb+1) 的,所以可以根据这一条件来判断是房子还是牛

#include
using namespace std;
int mina,minb,maxa,maxb,ans,n,m;
char ch[80][80];
int dx[4]={1,-1,0,0};  //方位数组 
int dy[4]={0,0,1,-1};
void dfs(int x,int y)
{
	ch[x][y]='.';ans++;    //统计.的个数 
	if (ymaxa) maxa=y;    //行尾 
	if (x>maxb) maxb=x;    //列尾 
	for (int i=0;i<4;i++)
	{
		int xi=x+dx[i];
		int yi=y+dy[i];
		if (ch[xi][yi]=='#'&&xi<=n&&yi<=m&&xi>0&&yi>0) dfs(xi,yi); //满足情况 
	}
} 
int main()
{
	freopen("satel.in","r",stdin);
	freopen("satel.out","w",stdout);
    scanf("%d%d",&n,&m);
    int house=0,cow=0;
    for (int i=1;i<=n;i++)   //输入 
    {
        ch[0][0]=getchar();
        for (int j=1;j<=m;j++) ch[i][j]=getchar();
    }
	for (int i=1;i<=n;i++)
	 for (int j=1;j<=m;j++)
	  {
	  	if (ch[i][j]=='#')
	  	{
	  	  ans=0;mina=75;minb=75;maxa=0;maxb=0;
	  	  dfs(i,j);
	  	  int sum=(maxa-mina+1)*(maxb-minb+1);   //如果当前图为房子应该的点数 
		  if (sum!=ans) cow++;        //与房子点数不符 
		           else house++;      //与房子点数相符 
		} 
	  }
	printf("%d\n%d",house,cow);
}

 

你可能感兴趣的:(各次模拟赛)