第一次全程参加的CF比赛(虽然过了D题之后就开始干别的去了),人生第一次codeforces上分……(或许之前的比赛如果都参加全程也不会那么惨吧),终于回到了specialist的行列,感动~。虽然最后也只过了A、B、D3题,但能上分还是非常的激动不已呀。
先发出来A、B、D的参考解法,C比赛时读了题感觉自己可以做出来,但时间只剩20分钟了,索性弃疗……。
11.23 补充上了C的参考代码
A题:
用一些str函数应该也可以做,但考虑到字符串长度只有不到100以及题目整体不是很复杂,不如直接求解。
从头开始扫描,寻找为“ogo”的子串(注意扫到倒数第三个数就结束),如果扫到了那么就输出”***“并继续看“go"能重复多少个,这个过程都只用while循环控制一下就可以了。最后再从最后的位置到n用for循环(如果此时已经到头了那么for循环也不会也不需要进行了)
1 #include<stdio.h> 2 #include<bits/stdc++.h> 3 #include <iostream> 4 using namespace std; 5 char a[106]; 6 int n,i=0; 7 bool check() 8 { 9 if(a[i]=='o'&&a[i+1]=='g'&&a[i+2]=='o') 10 return true; 11 return false; 12 } 13 int main() 14 { 15 16 scanf("%d",&n); 17 scanf("%s",a); 18 while(i<=n-3) 19 { 20 if(check()) 21 { 22 i+=3; 23 while(a[i]=='g'&&a[i+1]=='o') 24 i+=2; 25 printf("***"); 26 } 27 else 28 { 29 printf("%c",a[i]); 30 i++; 31 } 32 } 33 for(int j=i;j<n;j++) 34 printf("%c",a[j]); 35 return 0; 36 }
B题:
只需要看从每个1能没有阻挡的直走到多少个0,将这些加起来即为所求的答案。所以扫一遍整个图,从每个1出发,向四周走,遇到1或走到边界停下,不然个数就+1。
1 #include<stdio.h> 2 #include<bits/stdc++.h> 3 #include <iostream> 4 using namespace std; 5 int n,m,an,ii,jj; 6 int lo[2000][2000],dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; 7 int main() 8 { 9 int i,j,k; 10 scanf("%d%d",&n,&m); 11 an=0; 12 for(int i=1;i<=n;i++) 13 { 14 for(int j=1;j<=m;j++) 15 scanf("%d",&lo[i][j]); 16 } 17 for(i=1;i<=n;i++) 18 { 19 for(j=1;j<=m;j++) 20 { 21 if(lo[i][j]==1) 22 { 23 for(k=0;k<4;k++) 24 { 25 ii=i; 26 jj=j; 27 while((ii>0&&ii<=n&&jj>0&&jj<=m&&lo[ii][jj]==0)||(ii==i&&jj==j)) 28 { 29 ii+=dir[k][0]; 30 jj+=dir[k][1]; 31 if(ii>0&&ii<=n&&jj>0&&jj<=m&&lo[ii][jj]==0) 32 {an+=1; 33 } 34 else break; 35 } 36 } 37 } 38 } 39 } 40 printf("%d ",an); 41 return 0; 42 }
C题
二分查找,先按汽车油箱容量递增排序,二分查找符合条件的油箱最小容量。再排序,找最低的价格。初始设定答案为一个很大的数,如果最后答案不变输出-1,不然输出新的最小价格。
1 #include<stdio.h> 2 #include<bits/stdc++.h> 3 #include <iostream> 4 using namespace std; 5 long long int k,n,x=0,dis[200005]; 6 long long int s,t,time1,an,l,r,mid; 7 bool cmp(long long x,long long y) 8 { 9 return x<y; 10 } 11 struct oh 12 { 13 long long cap,val; 14 }che[200005]; 15 bool cmp2(oh x,oh y) 16 { 17 if(x.cap!=y.cap) 18 return x.cap<y.cap; 19 else 20 return x.val<y.val; 21 } 22 bool cmp3(oh x,oh y) 23 { 24 return x.val>y.val; 25 } 26 int main() 27 { 28 scanf("%I64d%I64d%I64d%I64d",&n,&k,&s,&t); 29 long long int i,j; 30 dis[0]=0; 31 an=20000000005; 32 for(i=1;i<=n;i++) 33 { 34 scanf("%I64d%I64d",&che[i].val,&che[i].cap); 35 } 36 for(i=1;i<=k;i++) 37 { 38 scanf("%I64d",&dis[i]); 39 } 40 sort(dis+1,dis+k+1,cmp); 41 sort(che+1,che+n+1,cmp2); 42 dis[k+1]=s; 43 time1=0; 44 l=1;r=n; 45 while(l<=r) 46 { 47 mid=(l+r)/2; 48 for(j=1;j<=k+1;j++) 49 { 50 if(dis[j]-dis[j-1]>che[mid].cap) 51 break; 52 else 53 { 54 if(x<che[mid].cap-2*(dis[j]-dis[j-1])) 55 time1+=(dis[j]-dis[j-1]-x); 56 else 57 time1+=(3*(dis[j]-dis[j-1])-che[mid].cap); 58 } 59 } 60 if(j==k+2&&time1<=t) 61 { 62 r=mid-1; 63 } 64 else 65 { 66 l=mid+1; 67 } 68 time1=0; 69 } 70 if(r<n) 71 {sort(che+r+1,che+n+1,cmp3); 72 printf("%I64d ",che[n].val);} 73 else 74 printf("-1 "); 75 return 0; 76 }
D题
我的做法貌似有点麻烦。对整个字符串现在前面加上1,末尾加上1,之后扫描一遍,对于连续的0长度小于船长的部分直接填上1。并用he代表余下为0的个数,最少的操作数即为通过最少的操作达到he<船长*船个数的状态。(注意到射击1个1右面数第”船长“个0如果没有打中船,那么从这个1到那个位置之间所有的都一定不会是船的一部分)这样之后从左往右扫,遇到a[i]=1,a[i+1]=0就意味着从第i个数开始一定有不小于船长个连续的0,这样对其操作一定不会产生”浪费“,一定会是最优的操作。如果是1而下个数不是0,那么就是碰上连续1的情况,i++即可,如果是0的话,he--,继续扫描,注意要用一个计数变量记录连续这样的0有多少个,如果达到船长就意味着有必要进行一次操作,以求达到最优的解法。
#include<stdio.h> #include<bits/stdc++.h> #include <iostream> using namespace std; char a[200030]; int n,ge,len,st,en,i,j,he=0,k,cnt=0,an[200030],s,geshu,chang; int main() { scanf("%d%d%d%d",&n,&ge,&len,&k); a[0]='1'; scanf("%s",a+1); a[n+1]='1'; st=0;en=0; he=n-k; for(i=1;i<=n+1;i++) { if(a[i]=='1') { en=i; if(en-st-1>0&&en-st-1<len) {for(i=st+1;i<en;i++) a[i]='1'; he-=(en-st-1); } else if((en-st-1)%len!=0) { for(j=en-1;j>=en-(en-st-1)%len;j--) {a[j]='1'; he--; } } st=i; } } chang=len*ge; i=0; while(he>=chang) { if(a[i]=='1'&&a[i+1]=='0') { geshu=0; an[cnt]=i+len; cnt++; for(j=i+1;j<=i+len;j++) { a[j]='1'; } he-=len; i=i+len; } else{ if(a[i]=='1') { geshu=0; while(a[i]!='0') i++; i--; } else { if(geshu<len-1) { a[i]='1'; geshu++; he--; } else { he--; geshu=0; a[i]='1'; an[cnt]=i; cnt++; } } } } printf("%d ",cnt); for(i=0;i<cnt;i++) printf("%d ",an[i]); return 0; }
通过这次CF,发现或许自己没有自己之前想象的那么水,以后再参加比赛一定好好对待,全程参加,不再划水了。