relations的vector存储的就是Relation类型的数据,并不是指针,所以relations[i]访问Relation的成员就是直接用.,
但是joins的JoinSql里面存的是指针,并不是实际的数据,所以应当用->来访问其中的成员
结构体当中的SqlNode是它的成员,所以访问这个成员用的是. ;但如果要访问这个成员(指针)所指向的对象的成员,就需要用->了
选择
函数重载要求函数的参数个数不同或者参数类型不同。
因为调用函数的时候无法确认函数的返回类型,所以仅返回类型不同的函数都可以匹配,这样就造成二义性,所以仅仅是返回类型不同是不能重载的,
重载运算符可以保持原运算符的优先级和结合性不变
重载运算符,坚持4个“不”原则: 1)运算符操作数的个数; 2)运算符原有优先级; 3)运算符原有的结合性; 4)运算符原有的语法结构 均不能改变!!!
___________
6-4 2017final友元函数之全班同学的平均绩点
第一次没考虑count==0的情况,就是一开始就是no
会让第一个样例点过不去
加上对count==0的特判后可以过
double averagegrade(student *stu, int count){
double sum=0.0;//学分绩点之和
double sumS=0.0;//学分之和
if(count==0){
return 0;
}
for(int i=0;i<count;i++){
student cur=stu[i];
for(int j=0;cur.score[j]!=-1;j++){
sum+=(cur.score[j]*((cur.grade[j])/10-5));
sumS+=(cur.score[j]);
}
}
//cout<<sum/sumS<<endl;
return sum/sumS;
}
//要算每个学生的每门课程的学分绩点
//要累计每个学生的学分数
6-5 2017Final 乐观的中考生
pro1
很抽象的一个错误,原代码当中没有给head初始化,是一个NULL,所以需要特判一下对head为NULL的情况
pro2
在当前结点不满足情况时,没有跳过该结点,填上continue即可
pro3
addBatch的问题
问题出现在这里,一开始的head是空的,但是在循环中,是构建了newTask,然后插入到cur之后的,即每个子链表的head都是空的
但是为什么第一串的head是空,但是打印出来的却没问题?
空,确实是空的,但并不是NULL,它是有next的,指向下一个实结点,只是自身并没有任何数据
0 1 2 3
从0向后数3个,但实际上是应当要包含0自身的
pro3_real!
指针
这个就是看指针操作,newCur->next指向的位置和cur是一样的,因为newCur和cur都是指针,而并非深拷贝,所以newCur在设next=NULL时,
这个指针操作,设next,并不是去改变指针的指向,如果只是改变指针指向,如newCur的指向的话,怎么改都无所谓,并不会影响其它指针和数据
但是如果通过这个指针,以->的形式去修改其所指向的数据,修改的就不是指针的值,而是修改的指针所指向的数据的值,修改的是内存上的值
即newCur是在栈上的操作,而newCur->next就是在堆上、内存的操作
在newCur->next将next修改之后,下一行cur=cur->next取得的指针就也是NULL了,但如果cur=cur->next在上一行,就是从堆中取出指针值,赋给cur,之后newCur->next再怎么修改,也不会对cur造成影响
Task* getBatch(int m){
int key;
cin>>key;
Task *head=new Task;
Task *cur=head;
for(int i=0;i<m;i++){
Task *newTask=new Task;
cin>>newTask->ID>>newTask->load;
newTask->key=key;
newTask->next=NULL;
cur->next=newTask;
cur=cur->next;
}
return head;
}
void display(Task *head,int m){
if(head==NULL){
cout<<"OK"<<endl;
return;
}
Task *cur=head;
for(int i=0;i<m;i++){
if(cur->next==NULL){
cout<<"OK"<<endl;
return;
}
cur=cur->next;
}
cout<<cur->ID<<" "<<cur->key<<" "<<cur->load<<endl;
}//插入到头
//插入到尾/中间,需要知道插入的小链表的头部x1和尾部x2,需要记录原来cur的next
//cur->next=x1;x2->next=原cur->next
Task* addBatch(Task *head,Task *h){
if(h==NULL){
return head;
}
//获取小链表尾部
Task *tail=h;
while(tail){
if(tail->next==NULL){
break;
}
tail=tail->next;
}
//插入到头部的特判
if((head==NULL)||(h->key<head->key)){
tail->next=head;
return h;
}
//尾部/中间
Task *cur=head;
while(1){
Task *next=cur->next;//下一个位置
if(next==NULL){//插入到尾部
cur->next=h;
return head;
}
if(next->key>h->key){//插入到cur的后面,中间位置
cur->next=h;
tail->next=next;
return head;
}
cur=next;
}
}
Task* study(Task*head, int mi, int ma, int load){
if(head==NULL){
return NULL;
}
Task *newHead=head;
Task *newCur=newHead;
Task *cur=head;//遍历原链表的每个元素
while(1){
//不满足条件的情况,直接跳过
if((cur->load>ma)||(cur->load<mi)){
newCur->next=cur;
newCur=newCur->next;
newCur->next=NULL;
cur=cur->next;
continue;
}
//做不完了,退出
if(load<cur->load){
newCur->next=cur;
display(newHead,3);
return newHead;
}
//做任务
load-=cur->load;
//如果做完了就退出
Task *next=cur->next;
if(next==NULL){
display(newHead,3);
return newHead;
}
cur=next;
}
}
//每批作业具有相同的优先值(不同批的任务的优先值不一样),由若干个不同的任务组成,每个任务都有唯一的编号
//小林同学会把每批作业先按照编号顺序整理好,然后按照这批作业的优先值,放入活页夹里。接下来,她将按照任务在活页夹的顺序依次把作业完成
//该批作业的第三个任务或者活页夹中的第三个任务,如果任务数少于3个,她会愉快地说一声"OK"
/* 请在这里填写答案 */
Task* getBatch(int m) {
if (m < 1) {
return NULL;
}
int key;
cin >> key;
Task* head = new Task;
cin >> head->ID >> head->load;
head->key = key;
head->next = NULL;
Task* cur = head;
for (int i = 0; i < m-1; i++) {
Task* newTask = new Task;
cin >> newTask->ID >> newTask->load;
newTask->key = key;
newTask->next = NULL;
cur->next = newTask;
cur = cur->next;
}
cout << "此时构建的一串的头部是" << head->ID << " " << head->load << endl;
return head;
}
void display(Task* head, int m) {
if (head == NULL) {
cout << "OK" << endl;
return;
}
Task* cur = head;
for (int i = 0; i < m-1; i++) {
if (cur->next == NULL) {
cout << "OK" << endl;
return;
}
cur = cur->next;
}
cout << cur->ID << " " << cur->key << " " << cur->load << endl;
}//插入到头
//插入到尾/中间,需要知道插入的小链表的头部x1和尾部x2,需要记录原来cur的next
//cur->next=x1;x2->next=原cur->next
Task* addBatch(Task* head, Task* h) {
if (h == NULL) {
cout << "此时要插入的task为空" << endl;
return head;
}
if (head == NULL) {
cout << "此时头节点为NULL" << endl;
return h;
}
//获取小链表尾部
Task* tail = h;
while (1) {
if (tail->next == NULL) {
break;
}
tail = tail->next;
}
cout << "此时插入的一串小链表的尾部是" << tail->ID << " " << tail->load << endl;
//插入到头部的特判
if (h->key < head->key) {
tail->next = head;
return h;
}
//尾部/中间
Task* cur = head;
while (1) {
Task* next = cur->next;//下一个位置
if (next == NULL) {//插入到尾部
cur->next = h;
return head;
}
if (next->key > h->key) {//插入到cur的后面,中间位置
cur->next = h;
tail->next = next;
return head;
}
cur = next;
}
}
void printTask(Task* head) {
Task* cur = head;
while (1) {
cout << cur->ID << " ";
cur = cur->next;
if (cur == NULL) {
cout << endl;
return;
}
}
}
Task* study(Task* head, int mi, int ma, int load) {
if (head == NULL) {
return NULL;
}
//Task* newHead = head;
Task* newHead = new Task;//不能用上面一行初始化,不然默认最后都会包含第一个结点,此时newHead是空结点
Task* newCur = newHead;
Task* cur = head;//遍历原链表的每个元素
while (1) {
cout << "在学习时,遍历到的当前结点是 " << cur->ID << endl;
//不满足条件的情况,直接跳过
if ((cur->load > ma) || (cur->load < mi)) {
newCur->next = cur;
newCur = newCur->next;
cur = cur->next;
//newCur->next = NULL;
// cur = cur->next;
continue;
}
//做不完了,退出
if (load < cur->load) {
newCur->next = cur;
display(newHead->next, 3);
return newHead;
}
//做任务
load -= cur->load;
//如果做完了就退出
Task* next = cur->next;
if (next == NULL) {
newCur->next = NULL;
display(newHead->next, 3);//newHead为空结点,应当从下一个开始遍历
return newHead;
}
cur = next;
}
}
pro4
这是因为在当前节点不满足条件时,直接让cur=cur->next了,但是cur->next可能为空,即后几个结点不满足条件
所以需要依据cur->next的情况进行判断,如果不为空,说明还没到头,则continue
如果为空,说明到头了,直接return
Task* getBatch(int m){
int key;
cin>>key;
Task *head=new Task;
Task *cur=head;
for(int i=0;i<m;i++){
Task *newTask=new Task;
cin>>newTask->ID>>newTask->load;
newTask->key=key;
newTask->next=NULL;
cur->next=newTask;
cur=cur->next;
}
return head->next;
}
void display(Task *head,int m){
if(head==NULL){
cout<<"OK"<<endl;
return;
}
Task *cur=head;
for(int i=0;i<m-1;i++){
if(cur->next==NULL){
cout<<"OK"<<endl;
return;
}
cur=cur->next;
}
cout<<cur->ID<<" "<<cur->key<<" "<<cur->load<<endl;
}//插入到头
//插入到尾/中间,需要知道插入的小链表的头部x1和尾部x2,需要记录原来cur的next
//cur->next=x1;x2->next=原cur->next
Task* addBatch(Task *head,Task *h){
if(h==NULL){
return head;
}
//获取小链表尾部
Task *tail=h;
while(tail){
if(tail->next==NULL){
break;
}
tail=tail->next;
}
//插入到头部的特判
if((head==NULL)||(h->key<head->key)){
tail->next=head;
return h;
}
//尾部/中间
Task *cur=head;
while(1){
Task *next=cur->next;//下一个位置
if(next==NULL){//插入到尾部
cur->next=h;
return head;
}
if(next->key>h->key){//插入到cur的后面,中间位置
cur->next=h;
tail->next=next;
return head;
}
cur=next;
}
}
Task* study(Task*head, int mi, int ma, int load){
if(head==NULL){
return NULL;
}
Task *newHead=new Task;
Task *newCur=newHead;
Task *cur=head;//遍历原链表的每个元素
while(1){
//不满足条件的情况,直接跳过
if((cur->load>ma)||(cur->load<mi)){
newCur->next=cur;
newCur=newCur->next;
cur=cur->next;
continue;
}
//做不完了,退出
if(load<cur->load){
newCur->next=cur;
//display(newHead->next,3);
return newHead->next;
}
//做任务
load-=cur->load;
//如果做完了就退出
Task *next=cur->next;
if(next==NULL){
//display(newHead->next,3);//并不是在这里面进行打印,是结束后还有一个display
newCur->next=NULL;
return newHead->next;
}
cur=next;
}
}
//每批作业具有相同的优先值(不同批的任务的优先值不一样),由若干个不同的任务组成,每个任务都有唯一的编号
//小林同学会把每批作业先按照编号顺序整理好,然后按照这批作业的优先值,放入活页夹里。接下来,她将按照任务在活页夹的顺序依次把作业完成
//该批作业的第三个任务或者活页夹中的第三个任务,如果任务数少于3个,她会愉快地说一声"OK"
pro5
Task* getBatch(int m){
int key;
cin>>key;
Task *head=new Task;
Task *cur=head;
for(int i=0;i<m;i++){
Task *newTask=new Task;
cin>>newTask->ID>>newTask->load;
newTask->key=key;
newTask->next=NULL;
cur->next=newTask;
cur=cur->next;
}
return head->next;
}
void display(Task *head,int m){
if(head==NULL){
cout<<"OK"<<endl;
return;
}
Task *cur=head;
for(int i=0;i<m-1;i++){
if(cur->next==NULL){
cout<<"OK"<<endl;
return;
}
cur=cur->next;
}
cout<<cur->ID<<" "<<cur->key<<" "<<cur->load<<endl;
}//插入到头
//插入到尾/中间,需要知道插入的小链表的头部x1和尾部x2,需要记录原来cur的next
//cur->next=x1;x2->next=原cur->next
Task* addBatch(Task *head,Task *h){
if(h==NULL){
return head;
}
if(head==NULL){
return h;
}
//获取小链表尾部
Task *tail=h;
while(tail){
if(tail->next==NULL){
break;
}
tail=tail->next;
}
//插入到头部的特判
if(h->key<head->key){
tail->next=head;
return h;
}
//尾部/中间
Task *cur=head;
while(1){
Task *next=cur->next;//下一个位置
if(next==NULL){//插入到尾部
cur->next=h;
return head;
}
if(next->key>h->key){//插入到cur的后面,中间位置
cur->next=h;
tail->next=next;
return head;
}
cur=next;
}
}
Task* study(Task*head, int mi, int ma, int load){
if(head==NULL){
return NULL;
}
Task *newHead=new Task;
Task *newCur=newHead;
Task *cur=head;//遍历原链表的每个元素
while(1){
//不满足条件的情况,直接跳过
if((cur->load>ma)||(cur->load<mi)){
newCur->next=cur;
newCur=newCur->next;
//下一个cur可能是空的
Task *next=cur->next;
if(next!=NULL){
cur=next;
continue;
}else{
newCur->next=NULL;
return newHead->next;
}
}
//做不完了,退出
if(load<=cur->load){
newCur->next=cur;
//display(newHead->next,3);
return newHead->next;
}
//做任务
load-=cur->load;
//如果做完了就退出
Task *next=cur->next;
if(next==NULL){
//display(newHead->next,3);//并不是在这里面进行打印,是结束后还有一个display
newCur->next=NULL;
return newHead->next;
}
cur=next;
}
}
//每批作业具有相同的优先值(不同批的任务的优先值不一样),由若干个不同的任务组成,每个任务都有唯一的编号
//小林同学会把每批作业先按照编号顺序整理好,然后按照这批作业的优先值,放入活页夹里。接下来,她将按照任务在活页夹的顺序依次把作业完成
//该批作业的第三个任务或者活页夹中的第三个任务,如果任务数少于3个,她会愉快地说一声"OK"
唯一区别就在于做不完的条件,如果是<=就退出,那么此时的结点还是会包含进newHead链表里的,但如果==的话,实际上是可以完成的,所以就错了
把load<=改为<即可AC
7-6
#include<iostream>
#include<string>
using namespace std;
int main(){
string t1,t2;
cin>>t1>>t2;
int rt1=stoi(t1);
int mm=rt1%100;
int hh=rt1/100;
int pastmm=stoi(t2);
mm+=pastmm;
hh+=mm/60;
mm=mm%60;
cout<<hh<<mm<<endl;
return 0;
}
不要+的,知道原来问题出在哪了,当totalM为60时,最终结果是10
问题关键在于需要保证分钟必须是一个两位的
#include<iostream>
#include<string>
using namespace std;
int main(){
int rt1,pastmm;
cin>>rt1>>pastmm;
int mm=rt1%100;
int hh=rt1/100;
int totalM=hh*60+mm;
totalM+=pastmm;
printf("%d%02d",totalM/60,totalM%60);
return 0;
}
7-8 正整数A+B
//空格的处理,getline(cin,string)
//如何判断是正整数 isdigit(int c) stoi
#include<iostream>
#include<sstream>
using namespace std;
bool valid(string in){
if(in.empty()){
return false;
}
for(auto c:in){
if(!isdigit(c)){
return false;
}
}
return true;
}
int main(){
string in;
getline(cin,in);
istringstream iss(in);
string a,b;
if(getline(iss,a,' ')&&getline(iss,b)){
if(valid(a)&&valid(b)){
cout<<a<<" + "<<b<<" = "<<stoi(a)+stoi(b)<<endl;
}else if(valid(b)){
cout<<"? + "<<b<<" = ?"<<endl;
}else if(valid(a)){
cout<<a<<" + ? = ?"<<endl;
}else{
cout<<"? + ? = ?"<<endl;
}
}else{
cout<<" ? + ? = ?"<<endl;
}
return 0;
}
需要增加一段对数字处于1,1000以内的判断
此外优化了代码结构
//空格的处理,getline(cin,string)
//如何判断是正整数 isdigit(int c) stoi
#include<iostream>
#include<sstream>
using namespace std;
bool valid(string in){
if(in.empty()){
return false;
}
for(auto c:in){
if(!isdigit(c)){
return false;
}
}
int num=stoi(in);
if(num<1||num>1000){
return false;
}
return true;
}
int main(){
string in;
getline(cin,in);
istringstream iss(in);
string a,b;
getline(iss,a,' ');
getline(iss,b);
bool flag=true;
if(valid(a)){
cout<<a;
}else{
cout<<"?";
flag=false;
}
cout<<" + ";
if(valid(b)){
cout<<b;
}else{
cout<<"?";
flag=false;
}
cout<<" = ";
if(flag){
cout<<stoi(a)+stoi(b)<<endl;
}else{
cout<<"?";
}
return 0;
}
主要记住sstream、getline,stoi,isdigit的用法
7-9 个位数统计
#include<iostream>
#include<map>
using namespace std;
int main(){
string num;
cin>>num;
map<char,int>m;
for(auto c:num){
m[c]++;
}
for(auto item:m){
cout<<item.first<<":"<<item.second<<endl;
}
return 0;
}
主要就是复习map的使用
还有就是map中的元素,就是一个个的数对,并非指针,是实际的数据,直接通过.获取
7-10 考试座位号
#include<iostream>
#include<map>
using namespace std;
struct tmp{
string id;
int examId;
};
int main(){
map<int,tmp>m;
int n;
cin>>n;
for(int i=0;i<n;i++){
tmp* t=new tmp;
int tryId;
cin>>t->id>>tryId>>t->examId;
m[tryId]=*t;
}
cin>>n;
for(int i=0;i<n;i++){
int query;
cin>>query;
cout<<m[query].id<<" "<<m[query].examId<<endl;
}
return 0;
}
还是哈希表map,只不过要注意以下键和值,在查找时用的是键,通过键找到值,
要求打印出准考证号和考试号,所以值可以用一个结构体
结构体分配内存是在堆上,在创建时取得的是一个指针,所以在存的时候应当对指针解引用得到指针所指向的实际值
也可以让哈希表不存实际数据,就是存指针,然后修改以下数据访问方式,这样还能更节省一些内存
#include<iostream>
#include<map>
using namespace std;
struct tmp{
string id;
int examId;
};
int main(){
map<int,tmp*>m;
int n;
cin>>n;
for(int i=0;i<n;i++){
tmp* t=new tmp;
int tryId;
cin>>t->id>>tryId>>t->examId;
m[tryId]=t;
}
cin>>n;
for(int i=0;i<n;i++){
int query;
cin>>query;
cout<<m[query]->id<<" "<<m[query]->examId<<endl;
}
return 0;
}
7-11 念数字
stoi必须要求参数类型是string,char类型就不行
可以通过string str(1,char)来构造string
也可以通过ASCII码运算得到
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
string arr[11]={"fu","ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
int main(){
string in;
cin>>in;
// for(auto c:in){
// if(c=='-'){
// cout<<arr[0]<<" ";
// }else{
// cout<<arr[(c-'0')+1]<<" ";
// }
// }
for(size_t i=0;i<in.size();i++){
if(in[i]=='-'){
cout<<arr[0];
}else{
cout<<arr[(in[i]-'0')+1];
}
if(i!=in.size()-1){
cout<<" ";
}
}
return 0;
}
前一种方式会格式错误,就是最后不应该有一个空格
以后面这种方式进行遍历
也可以用map,代码更精简
map就是两种数据结构之间建立了一个映射关系,通过其中一个就能找到另一个
#include<iostream>
#include<string>
#include<sstream>
#include<map>
using namespace std;
string arr[11]={"fu","ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
int main(){
string in;
cin>>in;
map<char,string>m;
m['-']="fu";
m['0']="ling";
m['1']="yi";
m['2']="er";
m['3']="san";
m['4']="si";
m['5']="wu";
m['6']="liu";
m['7']="qi";
m['8']="ba";
m['9']="jiu";
// for(auto c:in){
// if(c=='-'){
// cout<<arr[0]<<" ";
// }else{
// cout<<arr[(c-'0')+1]<<" ";
// }
// }
for(size_t i=0;i<in.size();i++){
cout<<m[in[i]];
if(i!=in.size()-1){
cout<<" ";
}
}
return 0;
}
7-12 检查密码
测试二过不去的原因就是因为输入的字符串里面有空格
PTA上的题都要注意空格的问题
这是因为吸收了换行符,使其成为了输入的一个密码
应当多一个操作,getchar来消除空格
#include<iostream>
#include<string>
using namespace std;
bool check(string in){
bool hasNum=false;
bool hasLet=false;
for(auto c:in){
if(((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z'))){
hasLet=true;
}else if((c>='0')&&(c<='9')){
hasNum=true;
}else if(c=='.'){
continue;
}else{
cout<<"Your password is tai luan le."<<endl;
return false;
}
}
if(!hasNum){
cout<<"Your password needs shu zi."<<endl;
return false;
}
if(!hasLet){
cout<<"Your password needs zi mu."<<endl;
return false;
}
return true;
}
int main(){
int n;
cin>>n;
getchar();
for(int i=0;i<n;i++){
string in;
getline(cin,in);
// cout<<"此时输入,得到的字符串是"<<in<<endl;
if(in.size()<6){
cout<<"Your password is tai duan le."<<endl;
continue;
}
if(check(in)){
cout<<"Your password is wan mei."<<endl;
}
}
return 0;
}
7-13 谁是赢家
#include<iostream>
#include<string>
using namespace std;
int main(){
int caipan=0;
int vote1,vote2;
cin>>vote1>>vote2;
for(int i=0;i<3;i++){
int tmp;
cin>>tmp;
if(tmp==0){
caipan++;
}
}
if(caipan==3){
cout<<"The winner is a: "<<vote1<<" + "<<caipan<<endl;
return 0;
}
if(caipan==0){
cout<<"The winner is b: "<<vote2<<" + "<<3-caipan<<endl;
return 0;
}
if(vote1>vote2){
cout<<"The winner is a: "<<vote1<<" + "<<caipan<<endl;
}else{
cout<<"The winner is b: "<<vote2<<" + "<<3-caipan<<endl;
}
return 0;
}
7-14 不变初心数
就是lambda函数在用的时候,如果需要用到其它的lambda函数,就必须进行捕获
这个auto相当于其类型,是一种函数,不能直接指定为返回值类型
lambda函数的函数名类似于一种变量名
实际上真正的Lambda函数只有【】开始的那部分,前面只是类似于一种函数句柄
如排序时就可以直接定义lambda函数体而无需声明函数名
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a > b;
});
#include<iostream>
#include<string>
using namespace std;
//暴力:获取数的每位数字,进行相加
//然后乘,重复这一过程
int check(int num){
auto getSum=[](int num)->int{
int sum=0;
int cur=num;
while(cur){
sum+=(cur%10);
cur/=10;
}
return sum;
};
int sum=getSum(num);
auto subCheck=[getSum](int newNum,int sum)->bool{
return getSum(newNum)==sum;
};
for(int i=2;i<=9;i++){
if(!subCheck(i*num,sum)){
return -1;
}
}
return sum;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int num;
cin>>num;
int res=check(num);
if(res==-1){
cout<<"NO"<<endl;
}else{
cout<<res<<endl;
}
}
return 0;
}
7-15 新胖子公式
应该就是考察格式化输出,直接用printf即可
#include<iostream>
#include<string>
using namespace std;
int main(){
double a,b;
cin>>a>>b;
double res=a/(b*b);
printf("%0.1f\n",res);
if(res>25){
cout<<"PANG"<<endl;
}else{
cout<<"Hai Xing"<<endl;
}
return 0;
}
7-16 幸运彩票
太抽象了,写着写着蒙了,都忘了输入了
#include<iostream>
#include<string>
using namespace std;
bool check(string num){
int sum1=0;
int sum2=0;
for(int i=0;i<3;i++){
//cout<<"num[i]为"<<num[i]<<endl;
sum1+=(num[i]-'0');
}
for(int i=3;i<6;i++){
sum2+=(num[i]-'0');
}
//cout<<"此时sum1是 "<<sum1<<"sum2是 "<<sum2<<endl;
return sum1==sum2;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
string num;
cin>>num;
if(check(num)){
cout<<"You are lucky!"<<endl;
}else{
cout<<"Wish you good luck."<<endl;
}
}
return 0;
}
7-17 降价提醒机器人
#include<iostream>
#include<string>
using namespace std;
int main(){
int n;
double m,t;
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>t;
if(t<m){
printf("On Sale! %.1f\n",t);
}
}
return 0;
}
7-18 胎压监测
#include<iostream>
#include<string>
using namespace std;
//如果所有轮胎的压力值与它们中的最大值误差在一个给定阈值内,并且都不低于系统设定的最低报警胎压,则说明情况正常,不报警;
int main(){
int s[4];
int low,bias;
for(int i=0;i<4;i++){
cin>>s[i];
}
cin>>low>>bias;
int maxS=max(max(s[0],s[1]),max(s[2],s[3]));//对于数组应该有更优雅的方式
int cnt=0,index=0;
for(int i=0;i<4;i++){
if((abs(s[i]-maxS)>bias)||(s[i]<low)){
cnt++;
index=i;
}
if(cnt>=2){
cout<<"Warning: please check all the tires!"<<endl;
return 0;
}
}
if(cnt==1){
printf("Warning: please check #%d!\n",index+1);
}else{
cout<<"Normal"<<endl;
}
return 0;
}
一个更优雅的版本
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
int main() {
vector<int> pressures(4);
int low, bias;
// 读取输入
for (int i = 0; i < 4; ++i) {
cin >> pressures[i];
}
cin >> low >> bias;
// 找到最大胎压值
int maxPressure = *max_element(pressures.begin(), pressures.end());
// 统计需要报警的轮胎数量
int count = count_if(pressures.begin(), pressures.end(), [maxPressure, bias, low](int p) {
return abs(p - maxPressure) > bias || p < low;
});
// 输出结果
if (count >= 2) {
cout << "Warning: please check all the tires!" << endl;
} else if (count == 1) {
auto it = find_if(pressures.begin(), pressures.end(), [maxPressure, bias, low](int p) {
return abs(p - maxPressure) > bias || p < low;
});
int index = distance(pressures.begin(), it) + 1;
cout << "Warning: please check #" << index << "!" << endl;
} else {
cout << "Normal" << endl;
}
return 0;
}
7-19 大笨钟的心情
#include<iostream>
#include<string>
using namespace std;
int main(){
int arr[24];
for(int i=0;i<24;i++){
cin>>arr[i];
}
int query;
cin>>query;
if(query<1||query>24){
return 0;
}
while(1){
cout<<arr[query]<<" "<<(arr[query]>50?"Yes":"No");
cin>>query;
if(query>=1&&query<=24){
cout<<endl;
}else{
return 0;
}
}
return 0;
}
这个完全是因为没有审题,query是要0和23之间,自己写的是1和24之间,修改完即可
#include<iostream>
#include<string>
using namespace std;
int main(){
int arr[24];
for(int i=0;i<24;i++){
cin>>arr[i];
}
int query;
cin>>query;
if(query<0||query>23){
return 0;
}
while(1){
cout<<arr[query]<<" "<<(arr[query]>50?"Yes":"No");
cin>>query;
if(query>=0&&query<=23){
cout<<endl;
}else{
return 0;
}
}
return 0;
}
7-20 统计工龄
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main(){
int n;
cin>>n;
map<int,int>m;
for(int i=0;i<n;i++){
int tmp;
cin>>tmp;
m[tmp]++;
}
for(auto item:m){
cout<<item.first<<":"<<item.second<<endl;
}
return 0;
}
完全是map的题
7-22 符号配对
pro1
如何处理/*?这东西要占俩次识别
就是遇到/和*后,连着后面进行一次判断,然后让i++跳过这个整体,以免重复识别如/*/就行了
pro2
byd的switch,break是只能跳出switch的,跳不出包含switch的while和for
这点确实难用,不如if,else;
要直接改的话就加个flag,但是注意需要在while和for里一起加,不然会强制读完一行,可能会打出两个NO(如上所示)
#include <iostream>
#include <string>
#include <stack>
using namespace std;
stack<int> st;
bool exitFlag = false; // 标志变量,用于控制外部 while 循环的退出
bool check() {
// 检查栈是否为空,确保所有左括号都有匹配的右括号
if (!st.empty()) {
cout << "NO" << endl;
int value =st.top();
switch (value) {
case 1: cout << "/*-?"; break;
case 2: cout << "(-?"; break;
case 3: cout << "[-?"; break;
case 4: cout << "{-?"; break;
}
cout << endl;
return false;
}
return true;
}
void anotherP(int choice){
switch(choice){
case 1: cout << "/*-?"; break;
case 2: cout << "(-?"; break;
case 3: cout << "[-?"; break;
case 4: cout << "{-?"; break;
}
}
//入栈进行判断
//遇到右括号,得到栈顶
//如果栈内无元素,就报缺失左符号
//如果有元素,和右括号进行判断,如果不同,报缺失右符号
//最后检查栈是否为空,不为空就报此时栈顶的左符号缺失
int main() {
string text;
while (!exitFlag) { // 使用标志变量控制 while 循环
getline(cin, text);
//cout << "此次读取到的一行数据是" << text << endl;
for (size_t i = 0; i < text.size()&&!exitFlag; i++) {
switch (text[i]) {
case '/':
if ((i != text.size() - 1) && (text[i + 1] == '*')) {
st.push(1);
i++;
}
break;
case '(':
st.push(2);
break;
case '[':
st.push(3);
break;
case '{':
st.push(4);
break;
case '*':
if ((i != text.size() - 1) && (text[i + 1] == '/')) {
if (st.size() > 0) {
int value = st.top();
st.pop();
if (value != 1) {
cout << "NO" << endl;
//cout << "/*-?" << endl;
anotherP(value);
exitFlag = true; // 设置标志变量,跳出外部 while 循环
}
}
else { // 栈内无值,说明右过剩了
cout << "NO" << endl;
cout << "?-*/" << endl;
exitFlag = true; // 设置标志变量,跳出外部 while 循环
}
i++;
}
break;
case ')':
if (st.size() > 0) {
int value = st.top();
st.pop();
if (value != 2) {
cout << "NO" << endl;
anotherP(value);
exitFlag = true; // 设置标志变量,跳出外部 while 循环
}
}
else {
cout << "NO" << endl;
cout << "?-)" << endl;
exitFlag = true; // 设置标志变量,跳出外部 while 循环
}
break;
case ']':
if (st.size() > 0) {
int value = st.top();
st.pop();
if (value != 3) {
cout << "NO" << endl;
anotherP(value);
exitFlag = true; // 设置标志变量,跳出外部 while 循环
}
}
else {
cout << "NO" << endl;
cout << "?-]" << endl;
exitFlag = true; // 设置标志变量,跳出外部 while 循环
}
break;
case '}':
if (st.size() > 0) {
int value = st.top();
st.pop();
if (value != 4) {
cout << "NO" << endl;
anotherP(value);
exitFlag = true; // 设置标志变量,跳出外部 while 循环
}
}
else {
cout << "NO" << endl;
cout << "?-}" << endl;
exitFlag = true; // 设置标志变量,跳出外部 while 循环
}
break;
case '.':
if (text.size() == 1) {
if (check()) {
cout << "YES" << endl;
}
exitFlag = true; // 设置标志变量,跳出外部 while 循环
break;
}
}
}
}
return 0;
}
上面代码能过,但确实太屎山了,不想改了,就这样吧
7-23 栈操作的合法性
#include<iostream>
#include<string>
using namespace std;
int m;
bool check(string str){
int cnt=0;
for(auto c:str){
if(c=='S'){
if(cnt==m){
return false;
}
cnt++;
}
if(c=='X'){
if(cnt<=0){
return false;
}
cnt--;
}
}
if(cnt==0){
return true;
}else{
return false;
}
}
int main(){
int n;
cin>>n>>m;
for(int i=0;i<n;i++){
string s;
cin>>s;
if(check(s)){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
return 0;
}
7-24 链表去重
pro1
#include<iostream>
#include<string>
#include<map>
#include<set>
using namespace std;
struct node {
string add;//还是保留着吧,因为最后打印要地址
int key;
string nextAdd;
};
int main() {
map<string, node*>m;//记录地址与对应结点的映射
set<int>hasKey;
string beginAdd;
int n;
cin >> beginAdd >> n;
//构造地址和结点的映射表
for (int i = 0; i < n; i++) {
int key;
string tmp, add;
cin >> add >> key >> tmp;
node* nod = new node;
nod->key = key;
nod->nextAdd = tmp;
nod->add = add;
m[add] = nod;
}
//串起所有结点形成链表
node* head = m[beginAdd];
node* deleteH = new node;
node* dcur = deleteH;
node* cur = head;
hasKey.insert(abs(cur->key));
while (1) {
string nextAdd = cur->nextAdd;
if (nextAdd == "-1") {
break;
}
node* next = m[nextAdd];
//依据键值情况,决定怎么加
if (hasKey.find(abs(next->key)) != hasKey.end()) {//键值已经有了,加入到删除链表当中
dcur->nextAdd = next->add;
cur->nextAdd = next->nextAdd;//调整cur->next为被删除结点的下一个位置
dcur = m[dcur->nextAdd];//此时dcur指向的是被删除结点,与cur->next无关
dcur->nextAdd = "-1";
}else {//加入到链表当中
cur->nextAdd = next->add;
hasKey.insert(abs(next->key));
cur = m[cur->nextAdd];//向后移动链表结点
}
}
//调回头部,准备打印
cur = head;
dcur = m[deleteH->nextAdd];
auto display = [&m](node* list) {
while (1) {
string nextAdd = list->nextAdd;
cout << list->add << " " << list->key << " " << nextAdd << endl;
if (nextAdd == "-1") {
break;
}
else {
list = m[nextAdd];
}
}
};
display(cur);
display(dcur);
return 0;
}
pro2
#include<iostream>
#include<string>
#include<map>
#include<set>
using namespace std;
struct node {
string add;//还是保留着吧,因为最后打印要地址
int key;
string nextAdd;
};
int main() {
map<string, node*>m;//记录地址与对应结点的映射
set<int>hasKey;
string beginAdd;
int n;
cin >> beginAdd >> n;
//构造地址和结点的映射表
for (int i = 0; i < n; i++) {
int key;
string tmp, add;
cin >> add >> key >> tmp;
node* nod = new node;
nod->key = key;
nod->nextAdd = tmp;
nod->add = add;
m[add] = nod;
}
//串起所有结点形成链表
node* head = m[beginAdd];
node* deleteH = new node;
node* dcur = deleteH;
node* cur = head;
hasKey.insert(abs(cur->key));
while (1) {
string nextAdd = cur->nextAdd;
if (nextAdd == "-1") {
break;
}
node* next = m[nextAdd];
//依据键值情况,决定怎么加
if (hasKey.find(abs(next->key)) != hasKey.end()) {//键值已经有了,加入到删除链表当中
dcur->nextAdd = next->add;
cur->nextAdd = next->nextAdd;//调整cur->next为被删除结点的下一个位置
dcur = m[dcur->nextAdd];//此时dcur指向的是被删除结点,与cur->next无关
dcur->nextAdd = "-1";
}else {//加入到链表当中
cur->nextAdd = next->add;
hasKey.insert(abs(next->key));
cur = m[cur->nextAdd];//向后移动链表结点
}
}
//调回头部,准备打印
cur = head;
dcur = m[deleteH->nextAdd];
auto display = [&m](node* list) {
while (1) {
string nextAdd = list->nextAdd;
cout << list->add << " " << list->key << " " << nextAdd << endl;
if (nextAdd == "-1") {
break;
}
else {
list = m[nextAdd];
}
}
};
display(cur);
display(dcur);
return 0;
}
就是在打印的时候,如果(被删除)列表如果是空的话,就没有考虑,添上后即可
#include<iostream>
#include<string>
#include<map>
#include<set>
using namespace std;
struct node {
string add;//还是保留着吧,因为最后打印要地址
int key;
string nextAdd;
};
int main() {
map<string, node*>m;//记录地址与对应结点的映射
set<int>hasKey;
string beginAdd;
int n;
cin >> beginAdd >> n;
//构造地址和结点的映射表
for (int i = 0; i < n; i++) {
int key;
string tmp, add;
cin >> add >> key >> tmp;
node* nod = new node;
nod->key = key;
nod->nextAdd = tmp;
nod->add = add;
m[add] = nod;
}
//串起所有结点形成链表
node* head = m[beginAdd];
node* deleteH = new node;
node* dcur = deleteH;
node* cur = head;
hasKey.insert(abs(cur->key));
while (1) {
string nextAdd = cur->nextAdd;
if (nextAdd == "-1") {
break;
}
node* next = m[nextAdd];
//依据键值情况,决定怎么加
if (hasKey.find(abs(next->key)) != hasKey.end()) {//键值已经有了,加入到删除链表当中
dcur->nextAdd = next->add;
cur->nextAdd = next->nextAdd;//调整cur->next为被删除结点的下一个位置
dcur = m[dcur->nextAdd];//此时dcur指向的是被删除结点,与cur->next无关
dcur->nextAdd = "-1";
}
else {//加入到链表当中
cur->nextAdd = next->add;
hasKey.insert(abs(next->key));
cur = m[cur->nextAdd];//向后移动链表结点
}
}
//调回头部,准备打印
cur = head;
dcur = m[deleteH->nextAdd];
auto display = [&m](node* list) {
if (list == NULL) {
return;
}
while (1) {
string nextAdd = list->nextAdd;
cout << list->add << " " << list->key << " " << nextAdd << endl;
if (nextAdd == "-1") {
break;
}
else {
list = m[nextAdd];
}
}
};
display(cur);
display(dcur);
return 0;
}
7-25 愿天下有情人都是失散多年的兄妹
因为没有考虑到-1的情况
找到原因了,一个致命的问题是,输入的那些人的父母,可能就没有构成一个person加入到map表当中,就是它们的id只是出现在子女的person行当中,但是自己却并不存在,有的可能存在
#include<iostream>
#include<string>
#include<map>
using namespace std;
struct person {
string id;
char sex;
string fid;
string mid;
};
map<string, person*>m;
bool check(person* a, person* b, int dep) {//父母为1,祖父母为2,曾祖父母为3,高祖父母为4
// cout << "此时检查的俩人是" << a->id << " " << b->id <<"它们的父id分别是"<<a->fid<<" b:"<<b->fid<<endl;
// cout << "开始递归检查,此时深度为" << dep << endl;
if (dep >= 5) {
return true;
}
//如果不可考的话,那么相应性别的就不再进行检查,并且不再继续往上追溯
// //只要双方父亲有一个是-1,就无法再追溯
if ((a->fid == "-1") || (b->fid == "-1") /* || (a->mid == -1) || (b->mid == -1)*/) {
return true;
}
//检查爸爸
if ((a->fid != "-1") && (a->fid == b->fid)) {
return false;
}
//检查妈妈
if ((a->mid != "-1") && (a->mid == b->mid)) {
return false;
}
//对于不存在的人,也无法继续追溯,只好允许了
if ((m.find(a->fid) == m.end()) || (m.find(b->fid) == m.end())) {
return true;
}
return check(m[a->fid], m[b->fid], dep + 1);
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
person* p = new person;
string id, fid, mid;
char sex;
cin >> id >> sex >> fid >> mid;
p->id = id;
p->fid = fid;
p->mid = mid;
p->sex = sex;
m[id] = p;
}
cin >> n;
for (int i = 0; i < n; i++) {
string a, b;
cin >> a >> b;
if (m[a]->sex == m[b]->sex) {
cout << "Never Mind" << endl;
continue;
}
if (check(m[a], m[b], 1)) {
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}
}
return 0;
}
如果==-1的判断发生在下一层的话,会导致递归不好进行
所以不如把==-1的判断转移到本层
原因就是我自己写的是map,如果把==-1直接移到开始的话,会在递归的时候,在map当中根本找不到对应指针,从而报错
就是它最后查询的时候,可能会查询一开始压根就没插入的元素,那些人是只能在输入的时候被动创建的
一个自认为比较优雅的代码
#include<iostream>
#include<string>
#include<map>
using namespace std;
struct person {
char sex;
int fid, mid;
person() :sex('x'), fid(-1), mid(-1) {}
}p[100000];
bool check(int a, int b, int dep) {//父母为1,祖父母为2,曾祖父母为3,高祖父母为4//判断父母相等在0
//cout << "此时检查的俩人是" << a << " " << b << "它们的父id分别是" << p[a].fid << " b:" << p[b].fid << endl;
//cout << "开始递归检查,此时深度为" << dep << endl;
if ((a == -1) || (b == -1)) { return true; }//检查此层的人是否存在,把==-1的逻辑转移到每层的开始
if (dep >= 4) { return true; }
//检查此层人是否通亲
if ((p[a].fid != -1) && (p[a].fid == p[b].fid)) {
//cout << "父亲相同,为" << a << "和" << b << "a的父亲为" << p[a].fid << "b的父亲为" << p[b].fid << endl;
return false; }//检查爸爸
if ((p[a].mid != -1) && (p[a].mid == p[b].mid)) { return false; }//检查妈妈
return check(p[a].fid, p[b].fid, dep + 1) && check(p[a].fid, p[b].mid, dep + 1) && check(p[a].mid, p[b].fid, dep + 1) && check(p[a].mid, p[b].mid, dep + 1);
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
int id;
char sex;
int fid, mid;
cin >> id >> sex >> fid >> mid;
p[id].sex = sex;
p[id].fid = fid;
if(fid!=-1){p[fid].sex='M';}
p[id].mid = mid;
if(mid!=-1){p[mid].sex='F';}
//cout << "接收到的id是" << id << " 它的信息为" << p[id].sex << " " << p[id].fid << " " << p[id].mid << endl;
}
cin >> n;
for (int i = 0; i < n; i++) {
int a, b;
cin >> a >> b;
if (p[a].sex == p[b].sex) {
cout << "Never Mind" << endl;
continue;
}
if (check(a, b, 0)) {//必须从自己开始,不然会在一开始就丢情况
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}
}
return 0;
}
7-26 深入虎穴
一开始想的就是出口是1号门,然后从1号门开始bfs
#include<iostream>
#include<vector>
#include<queue>
#include<climits>
using namespace std;
// int arr[100005];//记录的是每扇门所能到达的最远位置
// //
int main(){
vector<vector<int>>graph;
int n;
cin>>n;
for(int i=0;i<n;i++){
int m,p;
vector<int>node;
cin>>m;
for(int j=0;j<m;j++){
cin>>p;
node.push_back(p);
}
graph.push_back(node);
}
vector<int>dis(n+1,INT_MAX);
queue<int>q;
// for(auto gate:graph[0]){
// q.push(gate);
// }
//int maxnum=1;
dis[1]=0;
q.push(1);
while(q.size()!=0){
int cur=q.front();
for(auto gate:graph[cur-1]){
q.push(gate);
if(dis[gate]==INT_MAX){
dis[gate]=dis[cur]+1;
}
}
//maxnum+=1;
//cout<<"当前到达的编号是"<<cur<<endl;
// if(q.size()==1){
// cout<<cur<<endl;
// break;
// }
q.pop();
}
int maxnum=0;
int index=1;
for(int i=1;i<=n;i++){
if(dis[i]>maxnum){
maxnum=dis[i];
index=i;
}
}
cout<<index<<endl;
//cout<<maxnum;
return 0;
}
如果有多个出口?没指定出口?
就是输入的时候的索引是从1开始的,但是存的时候是从0开始的
vector<int>n()就是动态分配内存
就是在原来的基础上,加一个入度,完成对入口的判断就行了
#include<iostream>
#include<vector>
#include<queue>
#include<climits>
using namespace std;
int n;
struct node {
int in;
vector<int>adj;
int dis;
node() :in(0), dis(-1) {}
};
int main() {
cin >> n;
vector<node>graph(n+1);
for (int i = 0; i < n; i++) {
int m, p;
cin >> m;
for (int j = 0; j < m; j++) {
cin >> p;
graph[i+1].adj.push_back(p);
graph[p].in++;
}
}
queue<int>q;
//遍历所有结点,
for (int i = 1; i <= n; i++) {
if (graph[i].in == 0) {
q.push(i);
graph[i].dis = 0;
break;
}
}
while (q.size() != 0) {
int cur = q.front();
for (int gate : graph[cur].adj) {
q.push(gate);
if (graph[gate].dis == -1) {
graph[gate].dis = graph[cur].dis + 1;
}
}
q.pop();
}
int maxnum = -1;
int index = 0;
for (int i = 1; i <= n; i++) {
//cout << "此时结点的距离为" << graph[i].dis << endl;
if (graph[i].dis > maxnum) {
maxnum = graph[i].dis;
index = i;
}
}
cout << index << endl;
//cout<<maxnum;
return 0;
}
考试&评价
每个人题不一样
考试机子上比较抽象的一点是在遍历vector的时候不能直接用int
可能是c++版本的问题?按照编译器信息,用long unsigned int遍历即可
byd三年考三次pta,大一程序设计,大二数据结构,大三换皮叫做专业能力测试(byd这叫专业能力?)
无敌了