消除类游戏

问题描述

消除类游戏是深受大众欢迎的一种游戏,游戏在一个包含有n行m列的游戏棋盘上进行,棋盘的每一行每一列的方格上放着一个有颜色的棋子,当一行或一列上有连续三个或更多的相同颜色的棋子时,这些棋子都被消除。当有多处可以被消除时,这些地方的棋子将同时被消除。现在给你一个n行m列的棋盘,棋盘中的每一个方格上有一个棋子,请给出经过一次消除后的棋盘。

请注意:一个棋子可能在某一行和某一列同时被消除。

输入格式

输入的第一行包含两个整数n, m,用空格分隔,分别表示棋盘的行数和列数。接下来n行,每行m个整数,用空格分隔,分别表示每一个方格中的棋子的颜色。颜色使用1至9编号。

输出格式

输出n行,每行m个整数,相邻的整数之间使用一个空格分隔,表示经过一次消除后的棋盘。如果一个方格中的棋子被消除,则对应的方格输出0,否则输出棋子的颜色编号。

输入样例

样例输入1

4 5

2 2 3 1 2

3 4 5 1 4

2 3 2 1 3

2 2 2 4 4

样例输出1

2 2 3 0 2

3 4 5 0 4

2 3 2 0 3

0 0 0 4 4

样例说明

棋盘中第4列的1和第4行的2可以被消除,其他的方格中的棋子均保留。

样例输入2

4 5

2 2 3 1 2

3 1 1 1 1

2 3 2 1 3

2 2 3 3 3

样例输出2

2 2 3 0 2

3 0 0 0 0

2 3 2 0 3

2 2 0 0 0

样例说明

棋盘中所有的1以及最后一行的3可以被同时消除,其他的方格中的棋子均保留。

评测用例规模与约定

所有的评测用例满足:1 ≤ n, m ≤ 30。

参考代码

#include <stdio.h>
int main()
{
int n,m;
int i,j;
int a[105][105],b[105][105];
scanf("%d %d",&n,&m);
for(i=0;i<n;i++) //输入
{
for(j=0;j<m;j++)
{
scanf("%d",&a[i][j]);
b[i][j]=1;
}
}
for(i=0;i<n;i++) //找出行中三个以上相同颜色的
{
for(j=0;j<m-2;j++)
{
if(a[i][j]==a[i][j+1] && a[i][j+1]==a[i][j+2])
{
b[i][j]=0; //找到后标记
b[i][j+1]=0;
b[i][j+2]=0;
}
}
}
for(i=0;i<m;i++) //找出列中三个以上相同颜色的
{
for(j=0;j<n-2;j++)
{
if(a[j][i]==a[j+1][i] && a[j+1][i]==a[j+2][i])
{
b[j][i]=0; //找到后标记
b[j+1][i]=0;
b[j+2][i]=0;
}
}
}
printf("\n");
for(i=0;i<n;i++) //输出
{
for(j=0;j<m;j++)
{
if(b[i][j]==0)
{
printf("%d ",b[i][j]);
continue;
}
printf("%d ",a[i][j]);
}
printf("\n");
}
return 0;
}

0-1矩阵

问题描述

查找一个只包含0和1的矩阵中每行最长的连续1序列。

输入说明

输入第一行为两个整数m和n(0<=m,n<=100)表示二维数组行数和列数,其后为m行数据, 每行n个整数(0或1),输入数据中不会出现同一行有两个最长1序列的情况。

输出说明

找出每一行最长的连续1序列,输出其起始位置(从0开始计算)和结束位置(从0开始计算), 如果这一行没有1则输出两个-1,然后换行。

输入样例

5 6
1 0 0 1 1 0
0 0 0 0 0 0
1 1 1 1 1 1
1 1 1 0 1 1
0 0 1 1 0 0

输出样例

3 4
-1 -1
0 5
0 2
2 3

代码

#include<stdio.h>
int main() {
int m,n,b,c,d,e;
int i,j;
scanf("%d %d",&m,&n);
int a[m][n];
for(i=0; i<m; i++) {
for(j=0; j<n; j++) {
scanf("%d",&a[i][j]);
}
} //输入矩阵
for(i=0; i<m; i++) {
for(j=0,b=0,c=0,d=0,e=0; j<n; j++) {
if(a[i][j]==1)
b++; //b记录1字串长度
if(a[i][j]==0 && b>c) {
c=b; //用c来保存b的值
d=j-1; //d来记录此时的位置(此时是等于0时,所以是j-1)
b=0; //让b重新初始化进入下一行
}
if(a[i][j]==1 && b>c && j==n-1) { //此处判断行末为1时的情况
c=b;
d=j;
b=0;
}
if(a[i][j]==0) //若一行内没有1
e++;
}
if(e==n)
printf("%d %d\n",-1,-1);
else
printf("%d %d\n",d-c+1,d); //d是字串列末的位置
}
return 0;
}

等差数列

问题描述

请写一个程序,判断给定整数序列能否构成一个等差数列。

输入说明

输入数据由两行构成,第一行只有一个整数n(n<100),表示序列长度(该序列中整数的个数); 第二行为n个整数,每个整数的取值区间都为[-32768~32767],整数之间以空格间隔。

输出说明

对输入数据进行判断,不能构成等差数列输出“no”,能构成等差数列输出表示数列公差(相邻两项的差)的绝对值的一个整数。

输入样例

样例1输入

6
23 15 4 18 35 11

样例2输入

5
2 6 8 4 10

输出样例

样例1输出

no

样例2输出

2

代码

#include<stdio.h>
int main()
{
int n,i,j,k,temp,d,flag=0;
scanf("%d",&n);
int a[n];
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
} //输入数组
//首先对数列从小到大排序
for(j=1;j<n;j++)
{
for(i=0;i<n-j;i++)
{
if(a[i]>a[i+1])
{
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp; //数据交换
}
}
}
//再判断每两个数之间是否为等差
d=a[1]-a[0];
for(k=0;k+2<n;k++)
{
if(a[k+1]-a[k]!=a[k+2]-a[k+1])
{
flag=1;
break;
}
else
flag=0;
}
if(flag==1)
{
printf("no\n");
}
else
{
printf("%d\n",d);
}
return 0;
}

马鞍点

问题描述

若一个矩阵中的某元素在其所在行最小而在其所在列最大,则该元素为矩阵的一个马鞍点。 请写一个程序,找出给定矩阵的马鞍点。

输入说明

输入数据第一行只有两个整数m和n(0<m<100,0<n<100),分别表示矩阵的行数和列数; 接下来的m行、每行n个整数表示矩阵元素(矩阵中的元素互不相同),整数之间以空格间隔。

输出说明

在一行上输出马鞍点的行号、列号(行号和列号从0开始计数)及元素的值(用一个空格分隔),之后换行;若不存在马鞍点,则输出一个字符串“no”后换行。

输入样例

4  3
11 13 121
407 72 88
23 58 1
134 30 62

输出样例

1 1 72

思路:

  1. 找出每一行的最小值,并记录列号

  2. 判断是否为每一列的最大值

  3. 正常退出循环,则为马鞍点

#include<stdio.h>
int main(void){
int m,n;
int i,j,k,min,index,flag=0;
printf("请输入行号和列号:");
scanf("%d%d",&m,&n);
int array[m][n];
//输入数据
printf("输入数据\n");
for(i=0;i<m;i++){
for(j=0;j<n;j++){
scanf("%d",&array[i][j]);
}
}
//计算马鞍点
for(i=0;i<m;i++){
//找出每一行最小的点
min=array[i][0];
index=0; //记录最小值的列号
for(j=0;j<n;j++){
if(min>array[i][j]){
min=array[i][j];
index=j; //记录此时列数
}
}
//判断是否为这一列的最大值 列号为index
for(k=0;k<m;k++){
if(min<array[k][index]){//不是最小值 退出循环
break;
}
}
//判断是否正常退出循环,正常则为马鞍点
if(k==m){
printf("%d %d %d\n",i,index,min);
flag=1;
}
}
if(flag==0){ //判断程序是否有马鞍点
printf("no\n");
}
return 0;
}

水仙花数

问题描述

水仙花数是指一个 n 位数 ( n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身。 (例如:1^3 + 5^3 + 3^3 = 153)。 定义一个函数int function(int a, int b),计算区间[a,b]或区间[b,a]上水仙花数的个数。

说明

输入由两个整数a和b构成,a和b之间用空格分隔。0<a,b<10000

输出说明

输出区间[a,b]或区间[b,a]上水仙花数的个数。

输入样例

3 1000 

输出样例

4

提示

a,b的位数n可能小于3

代码

#include<stdio.h>
int function(int a,int b);
int main(){//因为啊,题目并没有给我们一个主函数,所以就自己写一个啦,为了好在本地测试用
int m,n,k;
scanf("%d %d",&m,&n);
k=function(m,n);
printf("%d",k);
}
int function (int m,int n){
int i,j,temp,k=0;
int sum,a[5]={0};

if(m>n){//保证m<n
i=m;
m=n;
n=i;
}
for(;m<n;m++){//进入循环,注意m是循环的条件,所以不能有变动
sum=0;
temp=m;//因此我们引入temp来进行计算
for(i=0;temp/10!=0;i++){//将位数存入数组
a[i]=temp%10;
temp=temp/10;
}
a[i]=temp;
for(j=0;j<=i;j++){ /*判断是否为水仙花数,注意题目判定一位独身数不为水仙花数*/
if(i==2) sum+=a[j]*a[j]*a[j];
if(i==3) sum+=a[j]*a[j]*a[j]*a[j];
}
if(sum==m)k++;//存水仙花的个数,妙哇
}
return k;
}

更新C++代码

#include <bits/stdc++.h>
using namespace std;

void f(int a, int b) {
stack<int>s;
int cn = 0;
if (b < 100) {
cout << 0;
return;
}
while (a <= b) {
int n = a;
int sum = 0;
while (n >= 1) {
s.push(n % 10);
n /= 10;
}
while (!s.empty()) {
int num = s.top();
s.pop();
sum += num * num * num;
}
if (sum == a)cn++;
a++;
}
cout << cn;
return;
}

int main() {
int a, b;
cin >> a >> b;
a < b ? f(a, b) : f(b, a);
return 0;
}

画图

问题描述

在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形,指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色。

下图给出了一个画了两个矩形的例子。第一个矩形是(1,1) 到(4, 4),用绿色和紫色表示。第二个矩形是(2, 3)到(6, 5),用蓝色和紫色表示。

图中,一共有15个单位的面积被涂上颜色,其中紫色部分被涂了两次,但在计算面积时只计算一次。在实际的涂色过程中,所有的矩形 都涂成统一的颜色,图中显示不同颜色仅为说明方便。给出所有要画的矩形,请问总共有多少个单位的面积被涂上颜色。

输入说明

输入的第一行包含一个整数n,表示要画的矩形的个数,1<=n<=100

接下来n行,每行4个非负整数,分别表示要画的矩形的左下角的横坐标与纵坐标,以及右上角的横坐标与纵坐标。0<=横坐标、纵坐标<=100。

输入说明

输入的第一行包含一个整数n,表示要画的矩形的个数,1<=n<=100

接下来n行,每行4个非负整数,分别表示要画的矩形的左下角的横坐标与纵坐标,以及右上角的横坐标与纵坐标。0<=横坐标、纵坐标<=100。

输入样例

2 
1 1 4 4
2 3 6 5

输出样例

15

代码

#include<stdio.h>
int main() {
int n,i,j,k,sum=0;
int x1,x2,y1,y2;
scanf("%d",&n);
int a[100][100]= {0};
for(k=0; k<n; k++) {
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
for(i=x1; i<x2; i++) {
for(j=y1; j<y2; j++) {
a[i][j]=1;
}
}
}
for(i=0; i<100; i++) {
for(j=0; j<100; j++) {
if(a[i][j]==1)
sum++;
}
}
printf("%d\n",sum);
return 0;
}

密码强度

问题描述

每个人都有很多密码,你知道你的密码强度吗? 假定密码由大写字母、小写字母、数字和非字母数字的符号这四类字符构成,密码强度计算规则如下:

  • 基础分:空密码(密码长度为零)0分,非空密码1分
  • 加分项1:密码长度超过8位,+1分
  • 加分项2:密码包含两类不同字符+1分,包含三类不同字符+2分,包含四类不同字符+3分

按照此规则计算的密码强度为0~5。请你设计一个程序计算给出的密码的强度。

输入说明

输入为一个密码字符串,字符串长度不超过50个字符。

输出说明

输出一个整数表示该密码的强度。

输入样例

输入样例1

abcd

输入样例2

ab123

输出样例

样例1输出

1

样例2输出

2

代码

#include<stdio.h>
#include<string.h>
int main() {
char s[50];
int i=0,a=0,b=0,c=0,d=0,sum=1,score=0;
gets(s);

if(strlen(s)==0) sum=0;
else if(strlen(s)>8) sum=2;

while(s[i]!='\0') {
if(s[i]>='A'&&s[i]<='Z') a=1;
else if(s[i]>='a'&&s[i]<='z') b=1;
else if(s[i]>='0'&&s[i]<='9') c=1;
else d=1;
i++;
}
score=a+b+c+d;
if(score==2) sum++;
else if(score==3) sum=sum+2;
else if(score==4) sum=sum+4;
printf("%d\n",sum);
return 0;
}

图像旋转

问题描述

旋转是图像处理的基本操作,在这个问题中,你需要将一个图像顺时针旋转90度。 计算机中的图像可以用一个矩阵来表示,为了旋转一个图像,只需要将对应的矩阵旋转即可。 例如,下面的矩阵(a)表示原始图像,矩阵(b)表示顺时针旋转90度后的图像。

输入说明

输入的第一行包含两个整数n和m,分别表示图像矩阵的行数和列数。1 ≤ n, m ≤ 100。 接下来n行,每行包含m个非负整数,表示输入的图像,整数之间用空格分隔。

输出说明

输出m行,每行n个整数,表示顺时针旋转90度之后的矩阵,元素之间用空格分隔。

输入样例

2 3
1 5 3
3 2 4

输出样例

3 1
2 5
4 3

代码

#include <stdio.h>
int main() {
int n, m;
scanf("%d %d", &n, &m);
int a[n][m], i, j;
for(i=0; i<n; i++)
for(j=0; j<m; j++)
scanf("%d", &a[i][j]);
for(j=0; j<m; j++) {
for(i=n-1; i>=0; i--)
printf("%d ", a[i][j]);
printf("\n");
}
return 0;
}

统计正整数个数

问题描述

统计n个正整数中每个数出现的次数。

输入说明

第一行是一个整数n(5<n<30),表示要待统计整数的个数; 第二行是n个整数,每个整数均小于100000

输出说明

按照整数从小到大的顺序依次输出不同的整数及其出现次数,整数和出现次数之间用冒号(:)分隔。

输入样例

12 
19 223 35 321 2 33 44 223 2 19 2 19

输出样例

2:3
19:3
33:1
35:1
44:1
223:2
321:1

代码

#include<stdio.h>
int main() {
int n,i,j,k;
scanf("%d",&n);
int a[n];
for(i=0; i<n; i++) {
scanf("%d",&a[i]);
}
for(i=0; i<n; i++) { //冒泡排序,从小到大输入
for(j=0; j<n-1; j++) {
if(a[j]>a[j+1]) {
k=a[j];
a[j]=a[j+1];
a[j+1]=k;
}
}
}
int count[n];
for (i = 0; i < n; i++) {
int sum = 1;
for (j = 1; j < n - i; j++)
if (a[i] == a[i + j]) { //判断有几个整数相等
sum++;
};
count[i] = sum;
}
for (i = 0; i < n; i++) {
printf("%d:%d\n", a[i], count[i]);
i=i+count[i]-1; //移除重复项
}
return 0;
}

移动

有n个整数,使前面各数顺序向后移m个位置,最后m个数变成前面m个数

解题思路

  1. 在函数中,新建一个数组,把原数组中的后m个数字先复制到这个新建的数组中
  2. 原数组中的元素向后移动m个位置
  3. 把新建数组中存贮的m个元素,复制到原数组中

注意点

​ “移动过程中数组的下标的计算要准确”

代码

#include <stdio.h>
#define N 80
int main()
{
int a[N], i;
int n, m;
int *p;
scanf("%d %d", &n, &m);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);

for (i = 0; i < m; i++)
*(p+i) = a[n - m + i]; //将最后m个数保存在指针中

for (i = n - 1; i >= m; i--)
a[i] = a[i - m]; //将n-m个数拉至数组a的尾部

for (i = 0; i < m; i++)
a[i] = *(p+i); //将保存在指针中的最后m个数赋值回数组a的前m个位置

for (i = 0; i < n; i++)
printf("%-3d", a[i]);

return 0;
}

围圈

问题描述

有n个人围成一圈,顺序排号,从第一个开始报数(从1到3报数),凡报到3的人退出圈子,问最后最后留下的是原来第几号的那位.

提示:用数组完成

代码

#include <stdio.h>
int main()
{
int n;
printf("输入人数:\n");
scanf("%d",&n);
int a[1000];
int i,temp;
int count = 0;
temp = n;
for(i = 0;i < n;i++)
{
a[i] = i+1;
}
i = 0;
while (n>1)
{
if(a[i] != 0) //不改变第一次报数值,只是让数字3的人为0
{
count++;
}
if(count == 3)
{
a[i] = 0; //让数到3的人为0
count = 0;
n--; //人数-1
}
i++;
if(i == temp)
{
i = 0;
}
}
for(i = 0;i < temp;i++)
{
if(a[i] != 0) //此时所有数到3的人都清零了,只有剩下的那一个不为0
{
printf("余下的为:%d号\n",a[i]);
}
}
return 0;
}