HNUCM-OJ算法练习13(JAVA,C)

算法练习13

  • 问题 A: 牛妹的蛋糕
  • 问题 B: 尼科彻斯定理
  • 问题 C: 油田问题
  • 问题 D: ABC + DEF = GHI
  • 问题 E: 马的遍历问题

问题 A: 牛妹的蛋糕

题目描述

众所周知,牛妹非常喜欢吃蛋糕。

第一天牛妹吃掉蛋糕总数三分之一多一个,第二天又将剩下的蛋糕吃掉三分之一多一个,以后每天吃掉前一天剩下的三分之一多一个,到第n天准备吃的时候只剩下一个蛋糕。

牛妹想知道第一天开始吃的时候蛋糕一共有多少呢?

输入

输入n,0

输出

输出第一天蛋糕的数量。

样例输入 Copy

2
4

样例输出 Copy

3
10

import java.util.Scanner;
  
public class Main {
   
  
    public static void main(String[] args) {
  
        Scanner cin = new Scanner(System.in);
        while(cin.hasNext()) {
      int  n=cin.nextInt();
      int cnt=1;
      for(int i=1;i<n;i++) {
          cnt=((cnt+1)*3)/2;
      }
      System.out.println(cnt);
      }
    }
}
 

问题 B: 尼科彻斯定理

题目描述

验证尼科彻斯定理,即:任何一个整数m的立方都可以写成m个连续奇数之和。

例如:

1^3=1

2^3=3+5

3^3=7+9+11

4^3=13+15+17+19

输入

多组输入,输入一个整数。

输出

输出分解后的字符串。

样例输入 Copy

6

样例输出 Copy

31+33+35+37+39+41

import java.util.Scanner;
  
public class Main {
    static void print_(int m,int i,boolean flag){
        if(flag==true){
            for(int k=0;k<m;k++){
                System.out.print(i+2*k);
              
              if(k<m-1) System.out.print("+");
            }
        }
        else System.out.print("-1");
          
    }
  
    public static void solve(int m) {
        boolean flag=false;
        int sum0=m*m*m;
        int sum1=0,start;
        for(int i=1;i<=sum0;i+=2){
             
            sum1=0;
            start=i;
            for(int j=0;j<m;j++){
              sum1=sum1+start;
              start+=2;
            }
            if(sum1==sum0) {
                flag=true;
                print_(m,i,flag);
                return;
            }
        }
          
        flag=false;
        print_(m,0,false);
  
  
    }
    public static void main(String[] args) {
   
        Scanner cin = new Scanner(System.in);
        while(cin.hasNext()) {
      int  n=cin.nextInt();
        
     StringBuffer str=new StringBuffer();
     solve(n);
     System.out.println();
      
        }
    }
}

问题 C: 油田问题

题目描述

输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块。如果两个字符“@”所在的格子相邻(横、竖或者对角线方向),即属于同一个八连块。

输入

多组输入
输入行数m,以及列数n。
然后输入*和@
1<=n,m<=100

输出

联通块个数

样例输入 Copy

5 5
****@
@@@
@**@
@@@
@
@@**@

样例输出 Copy

2

#include<cstdio>
#include<cstring>
const int maxn = 1000;
 
char arr[maxn][maxn];
int m, n, vist[maxn][maxn];
 
void dfs(int x, int y, int id){
    if (x < 0 || x >= m || y < 0 || y >= n)
        return;  //出界的格子
    if (vist[x][y]>0 || arr[x][y] != '@')return;
    vist[x][y] = id;//连通分量编号
    for (int dr = -1; dr <= 1;dr++)
    for (int dc = -1; dc <= 1;dc++)
    if (dr != 0 || dc != 0) dfs(x + dr, y + dc, id);//八个方向进行递归
 
}
 
int main()
{
    while (scanf("%d%d", &m, &n) == 2 && m&& n)
    {
        for (int i = 0; i < m; i++)
            scanf("%s", arr[i]);
        memset(vist, 0, sizeof(vist)); //用于标记已经访问过的格子
        int cnt = 0;
        for (int i = 0; i < m;i++)
        for (int j = 0; j < n;j++)
        if (vist[i][j] == 0 && arr[i][j] == '@')dfs(i, j, ++cnt);
        printf("%d\n", cnt);
    }
 
    return 0;
}

问题 D: ABC + DEF = GHI

题目描述

用1, 2, 3…9 这九个数字组成一个数学公式,满足:ABC + DEF = GHI,每个数字只能出现一次,编写程序输出所有的组合。

输入

输出

输出所有的 ABC + DEF = GHI,
每行一条数据,格式为ABC+DEF=GHI
输出结果按照ABC升序排列,如果ABC相同,则按照DEF升序排列

#include<cstdio>
#include<algorithm>
using namespace std;
int main(){
    int list[] = {1,2,3,4,5,6,7,8,9};
    do{
 int a = list[0]*100 + list[1]*10 + list[2];
    int b = list[3]*100 + list[4]*10 + list[5];
    int c = list[6]*100 + list[7]*10 + list[8];
    if(a + b == c)
        printf("%d+%d=%d\n", a, b ,c);
        }
 
    while(next_permutation(list,list+9));
    return 0;
}

问题 E: 马的遍历问题

题目描述

在5*4的棋盘中,马只能走斜“日”字。马从位置(x, y)处出发,把棋盘的每一格都走一次,且只走一次,请找出所有路径。

输入

x,y,表示马的初始位置。

输出

将每一格都走一次的路径总数,如果不存在该路径则输出“No solution!”。

样例输入 Copy

1 1
2 2

样例输出 Copy

32
No solution!

#include<iostream>
#include<stdio.h>
using namespace std;
 
int fx[8]= {1,2,2,1,-1,-2,-2,-1};
int fy[8]= {2,1,-1,-2,-2,-1,1,2};
 
static int count;
const static int n=5,m=4;
int a[n+1][m+1];  //用int二维数组来表示走的路劲
 
void dfs(int x,int y,int dep);//寻找路径的递归
int Check(int x,int y);//判断坐标是否出界,是否已经走过
 
int main()
{
    int x,y;
    while(scanf("%d%d",&x,&y)!=EOF){
    count=0;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
            a[i][j]=0;
 
    a[x-1][y-1]=1;
 
    dfs(x-1,y-1,2);
 
    if(count==0)
        cout<<"No solution!"<<endl;
    else
        cout<<count<<endl;
 
 
}
}
 
void dfs(int x,int y,int dep)
{
    int xx,yy;
    for(int i=0; i<8; i++)
    {
        xx=x+fx[i];
        yy=y+fy[i];
        if(Check(xx,yy)==1)
        {
            a[xx][yy]=dep;
            if(dep==n*m)
                count++;    //如果深度为n*m,那么表示遍历结束,就打印
            else
                dfs(xx,yy,dep+1);
            a[xx][yy]=0;     //回溯,恢复未走坐标。
        }
    }
}
 
int Check(int x,int y)
{
    //判断坐标是否出界,是否已经走过
    if(x<0||y<0||x>=n||y>=m||a[x][y]!=0)
        return 0;
    return 1;
}
 

你可能感兴趣的:(算法题)