软件设计期末OJ 思路+代码

[题目一:科学盛世]

某个杂志的主编想要找出最多的卓越科学家在世的年代。现在他的手上有这些科学家的出生与去世的年份(byear,eyear);如果某两个科学家的年份有交叉(10年以上,即一个的eyear-另一个的byear>=10),认为两人是“同在”,科学家同在最多的时代,称为“科学盛世”(一个科学家,只要跟另一个同在即可,而不是跟所有的都同在),请找出这个盛世的开始年和结束年。
思路:贪心算法皆可,排序后选出最大的

#include<bits/stdc++.h>
using namespace std;
typedef struct ListNode {
    int b;
    int e;
}year;//定义结构体,方便排序,也可以用pair
bool cmp(year a,year b){
    if(a.b!=b.b)
        return a.b<b.b;
    return a.e<b.e;
}//自定义排序cmp,要求第一个数从小到大,第二个数从小到大
int main(){
    int n;
    year y[2000];
    cin>>n;
    for(int i=0;i<n;i++)
        scanf("%d%d",&y[i].b,&y[i].e);
    sort(y,y+n,cmp);//对输入0-n进行排序
    int a=y[0].b,b=y[0].e; //用来记录最终左右边界,初始化
int l=y[0].b,r=y[0].e; //用来记录临时左右边界,初始化
    int mnum=0; //用来记录科学家数量,初始化0
    int num=0; //用来记录临时科学家数量,初始化0
    /*for(int i=0;i<n;i++){
        printf("%d %d\n",y[i].b,y[i].e);
    }*/
for(int i=0;i<n-1;i++){
//如果满足同在的条件则扩张边界max(y[i+1].e,r)
        if(y[i].e-y[i+1].b>=10||r-y[i+1].b>=10){
            num++;
            r=max(y[i+1].e,r);
        }else{
//如果不满足同在的条件则重新定义边界
            num=1;
            l=y[i+1].b;
            r=y[i+1].e;
        }
        if(num>mnum){
	//当前值大于最大值时更新
            mnum=num;
            b=r;
            a=l;
        }
    }
    printf("%d %d\n",a,b);
}

[题目二:找两数]

给定一个整数的数组,找出这样的两个数,这两个整数的和加起来等于一个特定的整数target,输出这样的数对。要求尽可能降低复杂度。提示:哈希方法或其他方法。

思路:定义一个哈希数组皆可,再定义一个记录输入顺序的数组,顺序输出

#include<bits/stdc++.h>
using namespace std;
int main(){
int num,target;
int a[100010]={0};//用来哈希记录输入的个数 
    int b[100010]={0};//用来记录输入的数的顺序
    int temp;
    int flag=0; //用来记录是否存在为0的情况
    scanf("%d",&num);
    scanf("%d",&target);
    for(int i=0;i<num;i++){
        scanf("%d",&temp);
        a[temp]++; //哈希记录输入
        b[i]=temp; //记录输入顺序
    }
    for(int i=0;i<num;i++){
        if(a[b[i]]>0&&a[target-b[i]]>0){ //保证大于零
            a[b[i]]--; //用掉了就-1
            if(a[target-b[i]]>0&&target-b[i]>=0){
            a[target-b[i]]--; //防止5+5=10的情况
            printf("%d %d\n",b[i],target-b[i]);
            flag=1;
            }
        }
    }
    if(!flag){
        printf("0 0\n");
	//考虑为0的情况
    }
}

[题目三:大数相加]

两组数据,要求使用结构体链表表示,每个节点只放一个数字:
struct ListNode {
int val;
struct ListNode *next;
};
Input: (2->4->3)+(5->6->4)
Output: 7->0->8

思路:正常链表相加,注意余数

#include<bits/stdc++.h>
using namespace std;
typedef struct LLNode {
    int val;
    struct LLNode *next;
} LL; //定义链表
int main(){
    LL *head1=new LL; //初始化链表1头节点
    LL *head2=new LL; //初始化链表2头节点
    LL  *tail1,*tail2;
    tail1=head1; //初始化链表1尾节点
    tail2=head2; //初始化链表2尾节点
    int flag=1,num1=0,num2=0; //flag表示遇到‘+’号时更换输入链表
    string str;
    cin>>str;
    int len=str.size();
    for(int i=0;i<len;i++){//遍历字符串并创建链表
        if(str[i]=='+'&&flag){
            flag=0;
        }
        if(flag&&str[i]<='9'&&str[i]>='0'){
            LL *node=new LL;
            node->val=str[i]-'0';
            node->next=NULL;
            tail1->next=node;
            tail1=node; 
		//创建节点并接入链表1
        }
        if(!flag&&str[i]<='9'&&str[i]>='0'){
            LL *node=new LL;
            node->val=str[i]-'0';
            node->next=NULL;
            tail2->next=node;
            tail2=node;
		//创建节点并接入链表2
        }

    }
    LL *head=new LL;
    LL  *tail=head,*p1,*p2;
    p1=head1->next;
    p2=head2->next;
    int c=0;
    while(p1||p2){
        LL *node=new LL;
if(p1&&p2){
//两个指针都不为空时相加
        node->val=(p1->val+p2->val+c)%10;
        c=(p1->val+p2->val+c)/10;
        p1=p1->next;
        p2=p2->next;
        node->next=NULL;
        tail->next=node;
        tail=node; //指向下一个节点

}else if(p1){
//一个指针都为空时相加
        node->val=(p1->val+c)%10;
        c=(p1->val+c)/10;
        p1=p1->next;
        node->next=NULL;
        tail->next=node;
        tail=node;
}else if(p2){
//一个指针都为空时相加
        node->val=(p2->val+c)%10;
        c=(p2->val+c)/10;
        p2=p2->next;
        node->next=NULL;
        tail->next=node;
        tail=node;
    }

    }
if(c){
//遇到余数不为零的情况需要再末尾补齐
        LL *node=new LL;
        node->val=c;
        node->next=NULL;
        tail->next=node;
        tail=node;
}
//输出
    head=head->next;
    printf("%d",head->val);
    while(head){
        head=head->next;
        if(head)
        printf("->%d",head->val);
    }
    printf("\n");
    return 0;
}

[题目四:砍几刀]

一根长度为n个单位的法棍,要切成长度为1的小段;一次可以同时切任意根,请输出切割所需要的最小次数。
思路:二分皆可,即对log2(输入)取整

#include<bits/stdc++.h>
using namespace std;
int main(){
    int num;
    scanf("%d",&num);
    double out1=log(num)/log(2);
    int out2=log(num)/log(2);
    if(out1-out2!=0) out2++/如果满足取整条件则+1
    printf("%d\n",out2);
}

[题目五:走路的学问]

如图:A到B的街区尺寸为4*5。A为左上,B为右下,从A走到B,只能向右或向下走,不绕路。输入A点和B点的坐标,如果街区之间的代价不一样,怎么求最短路径?

思路:DFS复杂度太大,直接动态规划即可,边界条件需要用两个数组来存转移方程b[i][j]=min(b[i][j-1]+a[i][j-1],b[i-1][j]+c[i-1][j]),只能向下或向右


```cpp
#include<bits/stdc++.h>
using namespace std;
struct ListNode {
    int val;
    struct ListNode *next;
};
int main(){
    int n;
    int a[150][150]; //左右运动记录
    int c[150][150]; //上下运动记录
    int b[150][150]={0};//最优代价记录
    cin>>n;
    for(int i=1;i<=2*n-1;i++){
        if(i%2==1){
        for(int j=1;j<=n-1;j++)
            scanf("%d",&a[(i+1)/2][j]);
        }else{
        for(int j=1;j<=n;j++)
            scanf("%d",&c[i/2][j]);
        }
    }
    for(int j=2;j<=n;j++)
        b[j][1]=b[j-1][1]+c[j-1][1]; //左右运动初始化边界条件
    for(int j=2;j<=n;j++)
        b[1][j]=b[1][j-1]+a[1][j-1]; //上下运动初始化边界条件
    for(int i=2;i<=n;i++)
        for(int j=2;j<=n;j++)
	//循环来更新最终的结果
         b[i][j]=min(b[i][j-1]+a[i][j-1],b[i-1][j]+c[i-1][j]);
    printf("%d\n",b[n][n]);
}

[题目六:打印机的秘密]

很多打印机隐藏着某些信息,这些信息多数并没有对外开放。比如下面左图的打印内容中,包含了一些黄色的点,这些点表示了某些信息,一般情况下不会被注意到;如果采用伪色彩增强的方法,我们可以将其转换成右图,这样看起来更明显。

下面是Xerox DocuColor series的信息格式描述:
Xerox Docucolor Matrix
Below is a representations of the DocuColor matrix printed on each sheet, and how they might be interpreted. The fingerprint is a 8 row x 15 column matrix of yellow dots. Note on the drawing that they number columns starting at index 1.
The first row and first column are special. They represent a property called parity which we will discuss in a moment. Otherwise:
● columns 2 and 5 represent time (minutes and hours respectively)
● columns 6, 7, 8 represent a date
● columns 11, 12, 13, 14 represent a serial number
● columns 3,4,9,10,15 are ignored (reserved).

In the figure, the two rows at the bottom are not part of the matrix but are the interpretation of the columns for your benefit. Each row represents a power of two, and so each column represents a decimal number. Look at column 2. There is a dot in the row representing 2, 16 and
32. The sum of those is 50, which represents the minutes in the time. Notice we do not count the top row, the parity row, in any calculation. For column 5, there is a dot at 4 and 8, representing 12 hours. Thus the time this page was printed was 12:50. The other interpretations are done in
the same manner. Note that, for our purposes, we would interpret all of the serial number columns, so our expectation would be to print the serial number as 21052857 in that order.
Parity is a really easy concept to understand. We typically use parity on binary representations such as a binary string. To determine the parity of a binary string, you count the number of 1’s that occur in the string. If the 1’s count is even, then the parity for that string is 1, if the 1’s count is odd then the parity is 0.
Row 1 has its parity bit set (1). The row has 6 dots, even parity. The bit accurately represents the parity of the row. Row 8 has 5 dots, odd parity, value of 0, no dot. The only weird one is the top left corner. Does that represent the parity of the first column (all the
row parities) or the first row (the parity of all the columns). Has to be the parity of the column.
In the image above, For the column parity in column 2,representing a parity of 0. If we count the number of 1’s in the column there are three dots (three 1’s), so the parity is odd. The parity bit accurately reflects the parity of the column. Columns 3 and 4 have no dots. The parity of 0 is 1, so 3 and 4 are set to 1 (a dot). Column 5 has two dots (two 1’s), the parity is even, so the parity is 1 (a dot).
We cannot actually read the dots, so instead we read a file of the following form (this file representing dot patterns used in the image above).
1 0 1 1 1 0 1 1 1 0 1 0 1 0 1
1 0 0 0 0 0 0 0 0 1 0 0 0 0 1
1 1 0 0 0 0 0 0 0 1 1 0 0 0 1
1 1 0 0 0 1 0 0 0 1 1 1 0 1 0
0 0 0 0 1 0 0 0 0 1 1 1 0 0 1
0 0 0 0 1 1 1 1 0 1 0 1 1 1 1
0 1 0 0 0 0 1 0 0 1 0 0 0 0 0
1 0 0 0 0 1 0 1 0 1 1 0 1 1 0

要求:采用面向对象编程,提供构造函数、校验判断(校验码和实际数值是否一致)获取日期、时间、序列号等等成员函数。
思路:对应列求和即可

#include<bits/stdc++.h>
using namespace std;
class matrix{
private:
    int a[9][16];
    int sum(int col){
        int s=0;
        for(int j=1;j<=7;j++)
            s+=pow(2,7-j)*a[j+1][col];
        return s; //对应列求和
    };
public:
    matrix(){
    };
    void input(){
        for(int i=1;i<=8;i++){
        for(int j=1;j<=15;j++){
            cin>>a[i][j]; //输入值
        }
        }
    }
    void showtime(){//小时间输出
        int h=sum(5);
        int m=sum(2);
        if(h<10) //如果是个位数还需要多输出一个0
            printf("0");
        printf("%d:",h);
        if(m<10)
            printf("0");
        printf("%d",m);
        printf("\n");
    }
    void showdate(){//日期输出
        int y=sum(8)+2000;
        int m=sum(7);
        int d=sum(6);
        printf("%d-",y);
        if(m<10) //如果是个位数还需要多输出一个0
            printf("0");
        printf("%d-",m);
        if(d<10)
            printf("0");
        printf("%d",d);
        printf("\n");
    }
    void shownumber(){//序列号输出
        for(int i=14;i>=11;i--){
            int temp=sum(i);
            if(temp<10) //如果是个位数还需要多输出一个0
                printf("0");
            printf("%d",temp);
        }
        printf("\n");
    }
};
int main(){
    matrix m;
    m.input();
    m.showdate();
    m.showtime();
    m.shownumber();
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值