【PAT刷题】快速产出垃圾——2020-3-2
A1095
没哈希表可能会死,所以先写一半然后抄答案了。解决了输出在范围内时间的问题。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 struct Event{ 7 char name[10]; 8 int hh; 9 int mm; 10 int ss; 11 bool status; 12 bool valid; 13 }events[10010],tmp; 14 15 struct Pair{ 16 char name[10]; 17 int inhh; 18 int inmm; 19 int inss; 20 int outhh; 21 int outmm; 22 int outss; 23 }pairs[10010]; 24 25 struct bao 26 27 bool cmp(Event a,Event b){ 28 if(strcmp(a.name,b.name)!=0) return strcmp(a.name,b.name)<0; 29 else if(a.hh!=b.hh) return a.hh<b.hh; 30 else if(a.mm!=b.mm) return a.mm<b.mm; 31 else return a.ss<b.ss; 32 } 33 34 bool cmp1(Pair a,Event b){ 35 if(a.inhh!=b.hh) return a.inhh<b.hh; 36 else if(a.inmm!=b.mm) return a.inmm<b.mm; 37 else return a.inss<=b.ss; 38 } 39 40 bool cmp2(Pair a,Event b){ 41 if(a.outhh!=b.hh) return a.outhh>b.hh; 42 else if(a.outmm!=b.mm) return a.outmm>b.mm; 43 else return a.outss>b.ss; 44 } 45 int main(){ 46 int n,k; 47 scanf("%d%d",&n,&k); 48 for(int i=0;i<n;i++){ 49 char tmp[10]; 50 scanf("%s %d:%d:%d %s",events[i].name,&events[i].hh,&events[i].mm,&events[i].ss,tmp); 51 if(!strcmp(tmp,"out")) events[i].status = false; 52 else events[i].status = true; 53 } 54 sort(events,events+n,cmp); 55 // for(int i=0;i<n;i++){ 56 // printf("%s %02d:%02d:%02d",events[i].name,events[i].hh,events[i].mm,events[i].ss); 57 // if(events[i].status==true){ 58 // printf(" in\n"); 59 // } 60 // else printf(" out\n"); 61 // } 62 int next=0,io=0,idx=0,index=0; 63 while(next<n){ 64 if(strcmp(events[next+idx].name,events[next+idx-1].name)==0 || idx==0){ 65 if(events[idx+next].status==true){ 66 io=1; 67 } 68 else{ 69 io++; 70 if(io==2){ 71 strcpy(pairs[index].name,events[idx+next].name); 72 pairs[index].inhh =events[idx-1+next].hh; 73 pairs[index].inmm =events[idx-1+next].mm; 74 pairs[index].inss =events[idx-1+next].ss; 75 pairs[index].outhh =events[idx+next].hh; 76 pairs[index].outmm =events[idx+next].mm; 77 pairs[index].outss =events[idx+next].ss; 78 index++; 79 } 80 else{ 81 io=3; 82 } 83 } 84 idx++; 85 } 86 else{ 87 next=next+idx; 88 idx=0; 89 } 90 } 91 for(int i=0;i<k;i++){ 92 scanf("%d:%d:%d",&tmp.hh,&tmp.mm,&tmp.ss); 93 int num=0; 94 for(int j=0;j<index;j++){ 95 if(cmp1(pairs[j],tmp) && cmp2(pairs[j],tmp)) num++; 96 //printf("%s %02d:%02d:%02d %02d:%02d:%02d\n",pairs[j].name,pairs[j].inhh,pairs[j].inmm,pairs[j].inss,pairs[j].outhh,pairs[j].outmm,pairs[j].outss); 97 } 98 printf("%d\n",num); 99 } 100 }
(2)抄一遍答案
答案说对于本题建议先学完配套用书的6.4节的mp的常用方法再来做……所以溜了溜了。能做就是太麻烦了。
好像之前散列表的没保存,也没太多值得写的,就算了
4.4 贪心
B1020
1 #include <cstring> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 6 struct Yuebing{ 7 double cunlaing; 8 double zongjia; 9 double danjia; 10 }yuebings[1010]; 11 12 bool cmp(Yuebing a,Yuebing b){ 13 return a.danjia>=b.danjia; 14 } 15 16 int main(){ 17 int n,d; 18 scanf("%d%d",&n,&d); 19 for(int i=0;i<n;i++){ 20 scanf("%lf",&yuebings[i].cunlaing); 21 } 22 for(int i=0;i<n;i++){ 23 scanf("%lf",&yuebings[i].zongjia); 24 yuebings[i].danjia = yuebings[i].zongjia/yuebings[i].cunlaing; 25 } 26 sort(yuebings,yuebings+n,cmp); 27 double xiaoliang = 0; 28 double yingli = 0; 29 for(int i=0;i<n;i++){ 30 xiaoliang += yuebings[i].cunlaing; 31 if(xiaoliang<=d){ 32 yingli+=yuebings[i].zongjia; 33 } 34 else{ 35 yingli+=yuebings[i].danjia*(d-xiaoliang+yuebings[i].cunlaing); 36 37 break; 38 } 39 } 40 printf("%.2f",yingli); 41 42 }
销量可能是double但是d是正整数,还挺怪的。
B1023
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 int ins[10]; 6 7 bool cmp(int a,int b){ 8 return a<=b; 9 } 10 11 int main(){ 12 for(int i=0;i<10;i++){ 13 scanf("%d",&ins[i]); 14 } 15 int idx =-1; 16 for(int i=1;i<10;i++){ 17 if(ins[i]!=0){ 18 printf("%d",i); 19 idx = i; 20 ins[i]--; 21 break; 22 } 23 } 24 for(int i=0;i<10;i++){ 25 for(int j=0;j<ins[i];j++){ 26 printf("%d",i); 27 } 28 } 29 }
白给。
区间贪心:所有区间都没有的部分不算数,剩下的就是短的,那么显然选短的。以此类推。从左到右和从右边到左都行,就是先固定一个排序方向然后找短的。
A1033
不会做,看答案。
(1)参考答案
贪心的策略就是找最近的比现在便宜的,然后加油到刚好到k,如果没有这样的直接加满,然后在最便宜的地方加油。实际上并不难就是自己想不到。
------------恢复内容开始------------
A1095
没哈希表可能会死,所以先写一半然后抄答案了。解决了输出在范围内时间的问题。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 struct Event{ 7 char name[10]; 8 int hh; 9 int mm; 10 int ss; 11 bool status; 12 bool valid; 13 }events[10010],tmp; 14 15 struct Pair{ 16 char name[10]; 17 int inhh; 18 int inmm; 19 int inss; 20 int outhh; 21 int outmm; 22 int outss; 23 }pairs[10010]; 24 25 struct bao 26 27 bool cmp(Event a,Event b){ 28 if(strcmp(a.name,b.name)!=0) return strcmp(a.name,b.name)<0; 29 else if(a.hh!=b.hh) return a.hh<b.hh; 30 else if(a.mm!=b.mm) return a.mm<b.mm; 31 else return a.ss<b.ss; 32 } 33 34 bool cmp1(Pair a,Event b){ 35 if(a.inhh!=b.hh) return a.inhh<b.hh; 36 else if(a.inmm!=b.mm) return a.inmm<b.mm; 37 else return a.inss<=b.ss; 38 } 39 40 bool cmp2(Pair a,Event b){ 41 if(a.outhh!=b.hh) return a.outhh>b.hh; 42 else if(a.outmm!=b.mm) return a.outmm>b.mm; 43 else return a.outss>b.ss; 44 } 45 int main(){ 46 int n,k; 47 scanf("%d%d",&n,&k); 48 for(int i=0;i<n;i++){ 49 char tmp[10]; 50 scanf("%s %d:%d:%d %s",events[i].name,&events[i].hh,&events[i].mm,&events[i].ss,tmp); 51 if(!strcmp(tmp,"out")) events[i].status = false; 52 else events[i].status = true; 53 } 54 sort(events,events+n,cmp); 55 // for(int i=0;i<n;i++){ 56 // printf("%s %02d:%02d:%02d",events[i].name,events[i].hh,events[i].mm,events[i].ss); 57 // if(events[i].status==true){ 58 // printf(" in\n"); 59 // } 60 // else printf(" out\n"); 61 // } 62 int next=0,io=0,idx=0,index=0; 63 while(next<n){ 64 if(strcmp(events[next+idx].name,events[next+idx-1].name)==0 || idx==0){ 65 if(events[idx+next].status==true){ 66 io=1; 67 } 68 else{ 69 io++; 70 if(io==2){ 71 strcpy(pairs[index].name,events[idx+next].name); 72 pairs[index].inhh =events[idx-1+next].hh; 73 pairs[index].inmm =events[idx-1+next].mm; 74 pairs[index].inss =events[idx-1+next].ss; 75 pairs[index].outhh =events[idx+next].hh; 76 pairs[index].outmm =events[idx+next].mm; 77 pairs[index].outss =events[idx+next].ss; 78 index++; 79 } 80 else{ 81 io=3; 82 } 83 } 84 idx++; 85 } 86 else{ 87 next=next+idx; 88 idx=0; 89 } 90 } 91 for(int i=0;i<k;i++){ 92 scanf("%d:%d:%d",&tmp.hh,&tmp.mm,&tmp.ss); 93 int num=0; 94 for(int j=0;j<index;j++){ 95 if(cmp1(pairs[j],tmp) && cmp2(pairs[j],tmp)) num++; 96 //printf("%s %02d:%02d:%02d %02d:%02d:%02d\n",pairs[j].name,pairs[j].inhh,pairs[j].inmm,pairs[j].inss,pairs[j].outhh,pairs[j].outmm,pairs[j].outss); 97 } 98 printf("%d\n",num); 99 } 100 }
(2)抄一遍答案
答案说对于本题建议先学完配套用书的6.4节的mp的常用方法再来做……所以溜了溜了。能做就是太麻烦了。
好像之前散列表的没保存,也没太多值得写的,就算了
4.4 贪心
B1020
1 #include <cstring> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 6 struct Yuebing{ 7 double cunlaing; 8 double zongjia; 9 double danjia; 10 }yuebings[1010]; 11 12 bool cmp(Yuebing a,Yuebing b){ 13 return a.danjia>=b.danjia; 14 } 15 16 int main(){ 17 int n,d; 18 scanf("%d%d",&n,&d); 19 for(int i=0;i<n;i++){ 20 scanf("%lf",&yuebings[i].cunlaing); 21 } 22 for(int i=0;i<n;i++){ 23 scanf("%lf",&yuebings[i].zongjia); 24 yuebings[i].danjia = yuebings[i].zongjia/yuebings[i].cunlaing; 25 } 26 sort(yuebings,yuebings+n,cmp); 27 double xiaoliang = 0; 28 double yingli = 0; 29 for(int i=0;i<n;i++){ 30 xiaoliang += yuebings[i].cunlaing; 31 if(xiaoliang<=d){ 32 yingli+=yuebings[i].zongjia; 33 } 34 else{ 35 yingli+=yuebings[i].danjia*(d-xiaoliang+yuebings[i].cunlaing); 36 37 break; 38 } 39 } 40 printf("%.2f",yingli); 41 42 }
销量可能是double但是d是正整数,还挺怪的。
B1023
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 int ins[10]; 6 7 bool cmp(int a,int b){ 8 return a<=b; 9 } 10 11 int main(){ 12 for(int i=0;i<10;i++){ 13 scanf("%d",&ins[i]); 14 } 15 int idx =-1; 16 for(int i=1;i<10;i++){ 17 if(ins[i]!=0){ 18 printf("%d",i); 19 idx = i; 20 ins[i]--; 21 break; 22 } 23 } 24 for(int i=0;i<10;i++){ 25 for(int j=0;j<ins[i];j++){ 26 printf("%d",i); 27 } 28 } 29 }
白给。
区间贪心:所有区间都没有的部分不算数,剩下的就是短的,那么显然选短的。以此类推。从左到右和从右边到左都行,就是先固定一个排序方向然后找短的。
A1033
不会做,看答案。
(1)参考答案
贪心的策略就是找最近的比现在便宜的,然后加油到刚好到k,如果没有这样的直接加满,然后在最便宜的地方加油。实际上并不难就是自己想不到。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 const int maxn = 510; 5 const int INF = 10000000000; 6 7 struct station{ 8 double price,dis; //价格、与起点的距离。 9 }st[maxn]; 10 11 bool cmp(station a,station b){ 12 return a.dis<b.dis; 13 } 14 15 int main(){ 16 int n; 17 double Cmax,D,Davg; 18 scanf("%lf%lf%lf%d",&Cmax,&D,&Davg,&n); 19 for(int i=0;i<n;i++){ 20 scanf("%lf%lf",&st[i].price,&st[i].dis); 21 } 22 st[n].price = 0; 23 st[n].dis =D; 24 sort(st,st+n,cmp); 25 if(st[0].dis!=0){ 26 printf("The maximum travel distance = 0.00\n"); 27 } 28 else{ 29 int now=0; 30 double ans =0,nowTank = 0,MAX= Cmax *Davg; 31 while(now <n){ 32 int k=-1; 33 double priceMin =INF; 34 for(int i =now+1;i<=n && st[i].dis-st[now].dis <=MAX;i++){ 35 if(st[i].price <priceMin){ 36 priceMin = st[i].price; 37 k=i; 38 if(priceMin<st[now].price){ 39 break; 40 } 41 } 42 } 43 if(k==-1) break; 44 double need = (st[k].dis - st[now].dis)/Davg; 45 if(priceMin < st[now].price){ 46 if(nowTank < need){ 47 ans+=(need-nowTank)*st[now].price; 48 nowTank =0; 49 } 50 else{ 51 nowTank -= need; 52 } 53 } 54 else{ 55 ans+=(Cmax- nowTank)*st[now].price; 56 nowTank = Cmax - need; 57 } 58 now = k; 59 } 60 if(now==n){ 61 printf("%.2f\n",ans); 62 } 63 else{ 64 printf("The maximum travel distance = %.2f\n",st[now].dis+MAX); 65 } 66 } 67 }
A1037
(1)自己尝试
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 bool cmp(int a,int b){ 7 return a>b; 8 } 9 10 int main(){ 11 int nc,np; 12 int cs[100010],ps[100010]; 13 scanf("%d",&nc); 14 for(int i=0;i<nc;i++){ 15 scanf("%d",&cs[i]); 16 } 17 scanf("%d",&np); 18 for(int i=0;i<np;i++){ 19 scanf("%d",&ps[i]); 20 } 21 sort(cs,cs+nc,cmp); 22 sort(ps,ps+np,cmp); 23 int sum=0; 24 for(int i=0;i<np && i<nc;i++){ 25 if(cs[i]>0 && ps[i]>0){ 26 sum+=cs[i]*ps[i]; 27 } 28 if(cs[nc-1-i]<0 && ps[np-1-i]<0){ 29 sum+=cs[nc-1-i]*ps[np-1-i]; 30 } 31 } 32 printf("%d",sum); 33 }
从后和从前遍历,注意数组别开小了。
A1067
这是一道需要认真读题的题,题目的意思其实是只能用0和其他数字交换,第二个参数是交换的次数, 然后是0~N-1的全排列,所以我们的思路应该是回归本位。没什么太好的思路,先抄下答案吧。
(1)参考答案
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 const int maxn= 100010; 5 int pos[maxn]; 6 int main(){ 7 int n,ans=0; 8 scanf("%d",&n); 9 int left = n-1,num; //left存放除0以外不在本位上的数的个数. 10 for(int i=0;i<n;i++){ 11 scanf("%d",&num); 12 pos[num] = i; 13 if(num==i && num!=0){ 14 left--; 15 } 16 } 17 int k=1; 18 while(left>0){ 19 if(pos[0] == 0){ 20 while(k<n){ 21 if(pos[k]!=k){ 22 swap(pos[0],pos[k]); 23 ans++; 24 break; 25 } 26 k++; 27 } 28 } 29 while(pos[0]!=0){ 30 swap(pos[0],pos[pos[0]]); //将0与Pos[0]交换. 31 ans++; 32 left--; 33 break; 34 } 35 } 36 printf("%d\n",ans); 37 return 0; 38 }
思路:
由于必须使用数字0跟其他数字进行交换,因此直观上可以很容易想到的策略是:如果数字0当前在i号位,则找到数字i当前所在的位置,然后把0和i进行交换。
但是这个策略不能完全解决问题,因为一旦交换过程中(或是初始序列时) 数字0回到了0号位,按上面的算法就不能将其与一个确定的数字交换,这是就要想办法处理这种情况。通过思考该策略,一旦一个非零的数字回到了它原先的位置,在后面的步骤中就不应该再让0去与它交换,否则会让交换次数变多。也就是说,非零的数字回到其“本位”后将不再变动。
这就得到一个启示:如果交换过程中出现数字0在0号位的情况,这就随意选择一个还没有回到“本位”的数字,让其与数字0交换位置。显然,这种交换不会对已经在”本位“的数字产生影响,但却使上边的策略的一致性。
具体实现上,可以使用int型变量left记录除零以外不在本位上的数字的个数,并在读入数据时预处理这些值。
注意点:
(1)在循环中寻找一个不在本位上的数时,如果每次都从开头开始枚举序列的中的数,判断其是否在本位上,则会有两组数据超时(因为复杂度是二次方级的)。更适合的做法是利用每个移回本位的数在后续操作中不再移动的特点,从整体上定义一个变量k,用来保存目前序列中不在本位上的最小数(初始为1),当交换过程中出现0回归本位的情况时,总是从当前的k开始继续增大寻找不在本位上的数,这样就能保证复杂度从整体上是线性级别(k在整个算法过程中最多只能从0增长到n)。
总结:反着存是为了减少存储次数,然后使用left和k也是为了减少存储次数。
这题先过,回头看,很怪。
A1038
这道题策略是返回S1+S2>S2+S1,即字符串拼接(想想js的字符串)
(1)参考答案
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 const int maxn=10010; 8 string str[maxn]; 9 bool cmp(string a,string b){ 10 return a+b<b+a; 11 } 12 13 int main(){ 14 int n; 15 cin >>n; 16 for(int i=0;i<n;i++){ 17 cin>>str[i]; 18 } 19 sort(str,str+n,cmp); 20 string ans; 21 for(int i=0;i<n;i++){ 22 ans+=str[i]; 23 } 24 while(ans.size()!=0 &&ans[0]=='0'){ 25 ans.erase(ans.begin()); //去除前导0 26 } 27 if(ans.size()==0) cout<<0; 28 else cout << ans; 29 }
两点,用string,注意处理0的情况。
4.5 二分
二分查找是基于有序序列的查找算法。时间复杂度是O(logn)
二分查找的过程与序列的下标是从0开始i还是从1开始无关。
需要三个索引。(left,right,mid)
三种二分:找到该数,找到第一个大于等于该数的数,找到第一个大于该数的数。
B1030/A1085
(1)自己尝试
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int maxn= 100010; 6 int ins[maxn]; 7 8 bool cmp(int a,int b){ 9 return a<b; 10 } 11 12 int search(int A[],int left,int right,long long np){ 13 int mid; 14 int i=left; 15 16 while(left<right){ 17 mid =(left+right)/2; 18 if(A[mid]>np){ 19 right = mid; 20 } 21 else{ 22 left=mid+1; 23 } 24 } 25 return left-i; 26 } 27 28 int main(){ 29 int n,p; 30 scanf("%d%d",&n,&p); 31 for(int i=0;i<n;i++){ 32 scanf("%d",&ins[i]); 33 } 34 sort(ins,ins+n,cmp); 35 int max= 0; 36 int tmp= 0; 37 for(int i=0;i<n;i++){ 38 tmp = search(ins,i,n,(long long)ins[i]*p); 39 if(tmp>max) max = tmp; 40 } 41 printf("%d",max); 42 }
考察了二分查找怎么写,mp可能是10*18所以可能越界,需要强制转换,然后在函数传入的时候也得改。
(2)参考答案
可以直接用库的。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 const int maxn = 100010; 5 int n,p,a[maxn]; 6 7 int main(){ 8 scanf("%d%d",&n,&p); 9 for(int i=0;i<n;i++){ 10 scanf("%d",&a[i]); 11 } 12 sort(a,a+n); //递增排序。 13 int ans=1; //最大长度,初值为1。 14 for(int i=0;i<n;i++){ 15 int j=upper_bound(a+i+1,a+n,(long long)a[i]*p)-a; //这里传入的是指针类型。 16 ans = max(ans,j-i); 17 } 18 printf("%d\n",ans); 19 return 0; 20 }

浙公网安备 33010602011771号