机考解题详情

跳台阶(典型递归)

递归方法:

假如有n个台阶,那第n个台阶只能由第n-1或者第n-2的台阶跳上来

#include <stdio.h>

int T(int n){
    if(n == 0||n == 1)
        return 1;

    else
        return T(n-1)+T(n-2);
}

int main(){

    int num;

    scanf("%d",&num);

    printf("%d",T(num));

    return 0;
}
View Code

迭代:

可以在数组中进行迭代依次求和

#include <stdio.h>

#define N 1000

int main(){

    int a[N],num;

    scanf("%d",&num);
    a[0] = 1;
    a[1] = 1; // 为了观看方便,a[0]不管;
    for(int i = 2;i <= num;i ++){
        a[i] = a[i-1] + a[i-2];
    }

    printf("%d",a[num]);

    return 0;
}
View Code

回文日期(不难,注意数据处理)

直接上代码,注释里有部分解释

 1 #include <stdio.h>
 2 
 3 #define N 1000
 4 
 5 int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
 6 //判断日期是否合法
 7 int check(int date){
 8     int year = date/10000;
 9     int month = date/100%100;
10     int day = date%100;
11     int flag = 1;
12     int leap;
13 
14 
15     if(!month || month>13 || !day)
16         flag = 0;
17 
18     if(month != 2 && day > months[month])
19         flag = 0;
20 
21     if(month == 2){
22         leap = (year % 4 == 0 && year % 100 || year % 400 == 0) ;//判断是不是闰年用到逻辑表达式 是就返回1,不是就返回0
23 
24         if(day > 28 + leap )
25             flag = 0;
26     }
27     return flag;
28 }
29 
30 
31  // 判断是否为回文日期
32 
33  int Ispd(int date){
34      int temp = 0;
35 
36      while (date > temp){
37             /*
38                 终止条件本应该是date是否等于0
39                 但由于我们知道给的数始终是偶数
40                 所以只需要判断从尾部倒过来到中
41                 间的数与从头但中间的数是否相等
42                 就可以判断是否为回文数
43             */
44         temp = temp * 10 + date%10;
45         date /= 10;
46      }
47      if(date == temp)
48         return 1;
49      else
50         return 0;
51  }
52 
53 
54  //判断是否为ABABBABA型日期
55  int IsAB(int date){
56      int d,m;
57      d = date % 100;
58      m = date / 100 % 100;
59 
60      if(Ispd(date) && d == m)
61         return 1;
62      else
63         return 0;
64  }
65 
66 
67 int main(){
68     int Num;
69     scanf("%d",&Num);
70 
71      for(int i = Num+1; i<89991231; i++){
72         if(check(i) && Ispd(i)){
73             printf("%d\n",i);
74             break;
75         }
76      }
77      for(int i = Num+1; i <= 89991231; i++){
78         if(check(i) && IsAB(i)){
79             printf("%d",i);
80             break;
81         }
82      }
83 
84     return 0;
85 }
View Code

子串分值

思路:

1.计算一个子串的值:

(1)可以去重再累加去求个数

(2)通过一个大小为26所有元素为0的数组,将每个字符的值减去a的ASCLL的值,就是其在26字母中的位置,然后将该位置的值赋值为1(相同的字母永远赋值的是同一个位置),所以最后通过循环,加起来,就是这个子串的值

2.就是找子串,这个就通过两个值,一个代表起始一个代表末端,就ok了

 1 #include <stdio.h>
 2 
 3 char str[100000];
 4 
 5 int Judge(int x,int y){ // 求子串的值,也就是求一个字符串的不同的字母
 6     int ans = 0;
 7     int last[26]={0};
 8     int i;
 9     for(i = x; i <= y; i ++){
10         last[str[i]-'a'] = 1;
11     }
12     for(i = 0;i <= 25; i++){
13         ans += last[i];
14     }
15     return ans;
16 }
17 
18 int main(){
19     int count =0;
20     int ans = 0;
21     int k = 0;
22     int i,j;
23     scanf("%s",str);
24     while(str[k]){
25         count++;
26         k++;
27     }
28     for(i = 0;i < count;i ++){
29         for(j = i;j < count;j ++){
30              ans += Judge(i,j); // 找子串,通过定下标,取出每个子串传进函数计算出子串值并求和
31         }
32     }
33     printf("%d",ans);
34 }
View Code

平面切分

思路:计算这些直线将平面分成了几个部分。
先去重,然后按照顺序每新增一个,新增的部分的个数=这一条线与前面的的线的交点个数+1,(暂时不用管后面学长讲)

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<set>
 4 using namespace std;
 5 set<pair<double,double> > se;
 6 const int N = 1005;
 7 double A[N];
 8 double B[N];
 9 set<pair<double,double> > s;
10 set<pair<double,double> >::iterator it;
11 int main()
12 {
13     int n,i,j,x,y;
14     cin>>n;
15     for(i=0;i<n;i++)
16     {
17         cin>>x>>y;
18         s.insert(make_pair(x,y));
19     }
20     n = s.size();
21     for(i=0,it=s.begin(),it++;it!=s.end();it++,i++)
22     {
23         A[i]=(*it).first;
24         B[i]=(*it).second;
25     }
26     long long ans=2;
27     for(i=1;i<n;i++)
28     {
29         set<pair<double,double> > se;
30         for(j=i-1;j>=0;j--)
31         {
32             double x=(B[j]-B[i])/(A[i]-A[j]);
33             double y=(A[j]*B[i]-A[i]*B[j])/(A[j]-A[i]);
34             se.insert(make_pair(x,y));
35         }
36         int n2=se.size();
37         ans+=(n2+1);
38     }
39     cout<<ans<<endl;
40 } 
View Code

 

跳跃游戏

最初的跳跃游戏是判断一个数组能否从头跳到尾,比如1 1 1 0 1;这种数组就不可能跳到尾,有兴趣的可以去做一下,可以直接用动态规划做

而我们这里的是在确保给定的数组是可以跳到尾的,让大家找到最小的跳跃次数

思路:动态规划要超时,所以用贪心算法(关于算法,后面有大佬给大家专门培训,可以去了解了解)

采用三个变量

cur:表示当前要覆盖到的最大小标

max:还没到cur结束之前的遍历到能覆盖的最大小标

res:用来表示结果

举个例子

[2,3,1,1,4];
一开始将res和cur初始化为0,分别表示步数为0和下标为0。max定义为一个小量(零或负数)。
利用贪心的思想,那么一开始(下标为0的位置)我就想走到最远的地方,也就是充分利用nums[0](也就是2)这个步长,但是,由于不知道在这个范围里面有没有更长的覆盖区间,那么,我就***先保留着这个当前最远的下标,也就是存入我的cur中然后先看看在这个范围里面***有没有比当前最大值更大的有的话先存到我的max中,如果遍历到了cur(i==cur)的时候,我就可以确定好在cur下标覆盖的范围里面我该走到多远了,也就是max(下标)。这就是循环的全部主体了。
值得注意的是我不需要遍历到最后一个,只需要遍历到倒数第二个就行了,因为到倒数第二个就已经可以确定最后结果了。

***如果上面看了还不懂:最开始能走的最大距离,然后记住这个下标,i循环到这个下标时,将这个下标内的最远覆盖距离max变成接下来的下一个要比较的下标,直到整个循环结束,有多少次这样的变化就是最少跳几次***

代码:

#include <stdio.h>

int jump(int nums[], int numsSize){
    if(numsSize<2)
    return 0;
    int i, j;
    int cur=0;
    int res=0;
    int max=-1;
    for(i=0;i<numsSize-1;i++)
    {
        max=max>i+nums[i]?max:i+nums[i]; // 记录最远覆盖距离
        if(cur==i)  // 一次最远距离结束的判断
        {
            res++;
            cur=max;  // 重新确定下一次的判断坐标
        }
    }
    return res;

}

int main(){
    int n;
    int nums[1000];
    
        scanf("%d",&n);
        
    for(int i = 0;i < n;i ++)
        
        scanf("%d",&nums[i]);
    
    printf("%d",jump(nums,n));

    return 0;
}
View Code

 

最小方差

后面算法大佬给你讲,代码emmmm...,放了你们也不一定能看懂

#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
int s[10][10], f[16][10][10][10][10];

int calc(int k, int x1, int y1, int x2, int y2) {
    int ans = INF;
    for (int i = x1 + 1; i < x2; i++) {
        ans = min(ans, f[k-1][x1][y1][i][y2] + f[1][i][y1][x2][y2]);
        ans = min(ans, f[k-1][i][y1][x2][y2] + f[1][x1][y1][i][y2]);
    }
    for (int i = y1 + 1; i < y2; i++) {
        ans = min(ans, f[k-1][x1][y1][x2][i] + f[1][x1][i][x2][y2]);
        ans = min(ans, f[k-1][x1][i][x2][y2] + f[1][x1][y1][x2][i]);
    }
    return ans;
}

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= 8; i++)
        for (int j = 1; j <= 8; j++) {
            scanf("%d", &s[i][j]);
            s[i][j] += s[i-1][j] + s[i][j-1] - s[i-1][j-1];
        }
    for (int x1 = 0; x1 < 8; x1++)
        for (int y1 = 0; y1 < 8; y1++)
            for (int x2 = x1 + 1; x2 <= 8; x2++)
                for (int y2 = y1 + 1; y2 <= 8; y2++) {
                    int p = s[x2][y2] - s[x1][y2] - s[x2][y1] + s[x1][y1];
                    f[1][x1][y1][x2][y2] = p * p;
                }
    for (int k = 2; k <= n; k++)
        for (int x1 = 0; x1 < 8; x1++)
            for (int y1 = 0; y1 < 8; y1++)
                for (int x2 = x1 + 1; x2 <= 8; x2++)
                    for (int y2 = y1 + 1; y2 <= 8; y2++)
                        f[k][x1][y1][x2][y2] = calc(k, x1, y1, x2, y2);
    printf("%.3f\n", sqrt((double)f[n][0][0][8][8] / n - (double)s[8][8] * s[8][8] / n / n));
    return 0;
}
View Code

 

posted @ 2020-11-09 22:14  cacolet  阅读(252)  评论(0)    收藏  举报