Codeforces Round #327 (Div2) A~E
CodeForces 591A
题意:在距离为L的两端A,B,相向发射魔法,a(以P1的速度)-->B,A<--b(以P2的速度)。假设a-->B,途中相遇,则返回到原点A<--a. 后又继续,a-->B,速度不变。
b亦是如此。求第二次相遇时a的位移。
思路:因为速度不变,所以第二次相遇地点与第一次相遇地点一样。
res= n/(Va+Vb)*Va
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 int main() 7 { 8 double n,a,b; 9 while(cin>>n>>a>>b) 10 cout<<n/(a+b)*a<<endl; 11 return 0; 12 }
CodeForces 591B
题意:给一个长度为n的字符串s,进行m (1 ≤ n, m ≤ 200 000)次操作。即:s: aba 操作m1:a b 则s变成:bab.求m次变换后的s.
思路:首先想到的是暴力模拟,但是n,m都是1e5,O(n*m)=1e10,会超时。
所以需要有技巧的暴力。
字符串由26个字母组成,每次操作我们只需将字母数组进行操作,保存下字母变换后的字母。最后扫一遍根据字母数组将s改过来就ok了
注意:处理字母变换后的字母时,每次需先找要变化的值,记录下标,最后再进行交换。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 char c[30],s[200005]; 7 int n,m; 8 9 int main() 10 { 11 for(int i=0;i<26;i++) 12 c[i]=char('a'+i); 13 while(~scanf("%d%d",&n,&m)) 14 { 15 16 scanf("%s",s); 17 char x[2],y[2]; 18 int p1,p2; 19 for(int i=0;i<m;i++) 20 { 21 scanf("%s%s",x,y); 22 for(int i=0;i<26;i++) 23 { 24 if(c[i]==x[0]) 25 p1=i; 26 if(c[i]==y[0]) 27 p2=i; 28 } 29 c[p1]=y[0]; 30 c[p2]=x[0]; 31 } 32 for(int i=0;i<n;i++) 33 s[i]=c[s[i]-'a']; 34 printf("%s\n",s); 35 } 36 return 0; 37 }
CodeForces 590A
题意:n个数字,只由0、1组成。数字进行0\1变换。
变换规则:1、首末数字保持不变B[1]=A[1],B[n]=A[n]
2、从左至右,第二个数A[i]开始,B[i]变成(A[i-1],A[i],A[i+1])的中位数
A->B一直变换,求达到稳定状态,即不能再变的变换次数,并输出最终变换后的B[]数字。
案例解释:
Case 1: 4
0 0 1 1
A[1-4]={0,0,1,1}
B[1]=A[1],B[4]=A[4]
A[1]:0 A[2]:0 A[3]:1 中位数为0,所以B[2]=0
A[2]:0 A[3]:1 A[4]:1 中位数为!,所以B[3]=1
B[1-4]={0,0,1,1}
A==B,所以无法变换
思路:每次都变换成中位数,最终要求是不变。
我们可发现连续两个0 0时第二个0不管右边为0还是1,该位都不会改变。1,1同理。
所以会发现:连续的0 或 连续的1 都是肯定不会变的。
那么我们可以找到所有连续的0、1,在剩下的数字中进行变换。并且剩下的数字中每个数一定会变,0->1,1->0。
再仔细一点会发现:最接近连续部分的数进行一次变换后一定会与相邻连续数一样。每个不连续数区间每次变换后不连续数分别从两端各减1;
因此我们可以根据不连续数长度求变换次数。
变换次数=max{不连续区间长度}/2+max{不连续区间长度}%2;
例如:1 1 0 1 0 1 1 不连续区间长度为3 1 1 0 1 0 1 1 0 1 0 0 最大不连续区间长度=max(3,2)=3
变更后,可以根据数字所在区间的长度及位置计算变换次数,奇变偶不变。
因此可转换成一般的模拟题。
注意:在进行变换的时候要多加注意。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 const int maxn=5*1e5+5; 7 8 int b[maxn],c[maxn],n; 9 10 int deal() 11 { 12 int maxlen=0,maxx=-1; 13 int s,e,k; 14 c[0]=b[0];c[n-1]=b[n-1]; 15 b[n+1]=b[n]=b[n-1]; 16 for(int i=1;i<=n;) 17 { 18 if(b[i]==b[i-1]) 19 { 20 c[i-1]=b[i];k=1; 21 e=i-2;s=e-maxlen+1; 22 while(s<e) 23 { 24 c[s]=abs(b[s]-(k%2)); 25 c[e]=abs(b[e]-(k%2)); 26 s++;e--,k++; 27 } 28 if(s==e) 29 c[s]=abs(b[s]-(k%2)); 30 } 31 while(i<=n&&b[i]==b[i-1]) 32 { 33 c[i]=b[i]; 34 i++; 35 maxx=max(maxx,maxlen/2+maxlen%2); 36 maxlen=0; 37 } 38 if(i<=n&&b[i]!=b[i+1]) 39 maxlen++; 40 i++; 41 } 42 return maxx; 43 } 44 45 int main() 46 { 47 while(~scanf("%d",&n)) 48 { 49 int g=0; 50 for(int i=0;i<n;i++) 51 scanf("%d",&b[i]); 52 printf("%d\n",deal()); 53 for(int i=0;i<n;i++) 54 if(g++) 55 printf(" %d",c[i]); 56 else 57 printf("%d",c[i]); 58 printf("\n"); 59 } 60 return 0; 61 }
CodeForces 590B
题意:一个飞船从起始点(x1,y1)飞向目标点(x2,y2),最大速度为V,方向不定,但是会刮风,风的速度向量在t前为(vx,vy),之后变为(Vx,Vy).现给定相应坐标以及速度大 小,求从起始点飞向目标点最少需要多长时间。
思路:二分时间。枚举时间tt,求出在tt时间内,风力单独在起始点作用产生的新位置,作为新的起点,再单独求飞船在tt时间内是否能从新起点至目标点。直到找到精度范围内最小 的tt.
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 double x1,y1,x2,y2,t,v,p1,q1,p2,q2; 7 const double d=0.000001; 8 9 double dis(double x1,double y1,double x2,double y2) 10 { 11 return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); 12 } 13 14 bool solve(double tt) 15 { 16 double stx,sty; 17 if(tt<=t) 18 { 19 stx=x1+p1*tt; 20 sty=y1+q1*tt; 21 } 22 else 23 { 24 stx=x1+p1*t+p2*(tt-t); 25 sty=y1+q1*t+q2*(tt-t); 26 } 27 double distance=dis(stx,sty,x2,y2); 28 if(distance<=tt*tt*v*v) 29 return 1; 30 return 0; 31 } 32 33 int main() 34 { 35 while(~scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2)) 36 { 37 scanf("%lf%lf%lf%lf%lf%lf",&v,&t,&p1,&q1,&p2,&q2); 38 double L=0,R=1e8,m; 39 while((R-L)>d) 40 { 41 m=(R+L)/2; 42 if(solve(m)) 43 R=m; 44 else 45 L=m; 46 } 47 printf("%.18lf\n",m); 48 } 49 return 0; 50 }
CodeForces 590C
题意:在n*m的地图上,有三个州“1”,“2”,“3”,每个州是一个整体。除了州,“#”不可开拓道路,“."可开拓道路。求使三个州连通(任一州可到达另一州)最少需要多少个.“
思路:三个州之间的道路,一定会有一个公共点。所以只需要求每个州到该点的最短路径,进行相加。
BFS,记录每个州到每个点的最短路径。
技巧:把所有“1”放入队列后开始搜,同理对“2”,“3”进行一样的操作。
注意:记录路径的时候,到当位置的路径=到前一位置路径+(前一位置=='.') 最后ans=min(ans,f[0][i][j]+f[1][i][j]+f[2][i][j]+(mp[i][j]=='.'))
或者按平常的记录方法,ans=min(ans,f[0][i][j]+f[1][i][j]+f[2][i][j]+(mp[i][j]=='.')-2)
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 const int maxn=1000+5; 8 const int inf=1e7; 9 10 int n,m,pre[4][2]={0,1,1,0,0,-1,-1,0}; 11 int f[5][maxn][maxn]; 12 char mp[maxn][maxn]; 13 14 struct node 15 { 16 int x,y; 17 }pos[maxn*maxn]; 18 19 void init() 20 { 21 for(int i=0;i<3;i++) 22 for(int j=0;j<n;j++) 23 for(int k=0;k<m;k++) 24 f[i][j][k]=inf; 25 } 26 27 bool judge(int xx,int yy) 28 { 29 if(xx<0||xx>=n||yy<0||yy>=m) 30 return 0; 31 return 1; 32 } 33 34 queue<node> q; 35 void bfs(int c) 36 { 37 char ch=c+'1'; 38 while(!q.empty()) 39 q.pop(); 40 41 node a,b; 42 for(int i=0;i<n;i++) 43 for(int j=0;j<m;j++) 44 if(mp[i][j]==ch) 45 { 46 a.x=i;a.y=j; 47 q.push(a); 48 f[c][i][j]=0; 49 } 50 while(!q.empty()) 51 { 52 a=q.front(); 53 q.pop(); 54 for(int i=0;i<4;i++) 55 { 56 int xx=a.x+pre[i][0]; 57 int yy=a.y+pre[i][1]; 58 if(!judge(xx,yy)||mp[xx][yy]=='#') 59 continue ; 60 if(f[c][xx][yy]>f[c][a.x][a.y]+(mp[a.x][a.y]=='.')) 61 { 62 f[c][xx][yy]=f[c][a.x][a.y]+(mp[a.x][a.y]=='.'); 63 b.x=xx,b.y=yy;q.push(b); 64 } 65 } 66 } 67 } 68 69 int deal() 70 { 71 int minn=inf; 72 for(int i=0;i<n;i++) 73 for(int j=0;j<m;j++) 74 minn=min(minn,f[0][i][j]+f[1][i][j]+f[2][i][j]+(mp[i][j]=='.')); 75 return minn; 76 } 77 78 int main() 79 { 80 while(~scanf("%d%d",&n,&m)) 81 { 82 for(int i=0;i<n;i++) 83 scanf("%s",mp[i]); 84 init(); 85 for(int i=0;i<3;i++) 86 bfs(i); 87 int mm=deal(); 88 printf("%d\n",(mm>=inf)?-1:mm); 89 } 90 return 0; 91 }