CodeForces - 138A Literature Lesson
题意:每组第一行给出两个数字n,k。接下来是4*n行,一共n小节,如果一个小节的4个单词从倒数第k个元音开始到单词结尾都一样 那这个小节就是aaaa型 ;第一个和第三个一样或第二个和第四个一样就是abab型;还有aabb行 abba型 ;其它就不是韵文。如果给出的所有小节都有同样的类型(aaaa可以看成是abba aabb abab的特殊情况 ) 就输出这首诗的类型 否则输出NO。
思路:这道题难点在于题目的理解,如果题目理解了,那这道题就很简单,把所有的情况考虑一遍就可以了。代码如下。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=10100; char s[5][N]; char w[5][N]; int n,m; int q[N]; int main() { scanf("%d%d",&n,&m); int flag=0,v=0; for(int i=1; i<=n; i++) { scanf("%s%s%s%s",s[1],s[2],s[3],s[4]); if(flag==1)continue; for(int j=1; j<=4; j++) { int d=strlen(s[j]),num=0,t=0,tag=0; for(int k=d-1; k>=0; k--) { char c=s[j][k]; if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u')//元音字母的判断 { num++; w[j][t++]=c; if(num==m){tag=1;break;} } else w[j][t++]=c; } if(tag==0)flag=1; w[j][t]='\0'; } if(flag==1)continue; int h[6]={0},ans=0; if(strcmp(w[1],w[2])==0)h[0]=1,ans++; if(strcmp(w[3],w[4])==0)h[1]=1,ans++; if(strcmp(w[1],w[3])==0)h[2]=1,ans++; if(strcmp(w[2],w[4])==0)h[3]=1,ans++; if(strcmp(w[2],w[3])==0)h[4]=1,ans++; if(strcmp(w[1],w[4])==0)h[5]=1,ans++; if(ans==6)q[++v]=1;//aaaa else if(h[0]==1&&h[1]==1)q[++v]=2;//aabb else if(h[2]==1&&h[3]==1)q[++v]=3;//abab else if(h[4]==1&&h[5]==1)q[++v]=4;//abba } int book[5]={0}; for(int i=1;i<=v;i++)book[q[i]]++; if(flag)printf("NO"); else if(book[1]==n)printf("aaaa\n"); else if(book[1]+book[2]==n)printf("aabb\n"); else if(book[1]+book[3]==n)printf("abab\n"); else if(book[1]+book[4]==n)printf("abba\n"); else printf("NO\n"); }
CodeForces - 1384B1 Koa and the Beach (Easy Version)
题意:n米的海和一个在n+1的点的岛组成。一个人测量了从海岸线1,2,…,n米到岛屿的海的深度,这个海有潮汐,潮汐的强度取决于参数k,参数k影响了海的深度,对于从时间t=0开始,前k秒,每过一秒导致所有海的深度+1,然后再k秒,潮汐每过一秒导致所有海的深度都 -1。这个过程不断地持续着,从0开始我们可以定义一个数组p=[0,1,2,...,k−2,k−1,k,k−1,k−2,...,2,1],长度为2k,在时间t,第i米的深度为di+p[tmodk]。这个人从海岸线开始游到岛屿,每一秒,他可以前进或者呆在原地,如果当且深度>l,那么这个人就会被淹死。求这个人如果可以到达岛屿输出YES,否则输出NO。
思路:这道题可以通过dp来做。dp [ i ] [ j ]当这个人到达第i片海域的时间为j秒这个状态是通过的
dp[ i ] [ j ] 可以由 dp[ i ] [ j - 1](上一秒在第 i 片海域选择不移动)和 dp[ i - 1 ] [ j - 1 ](上一秒在 i-1 片海域选择移动)两个状态状态转移达到,
只要两者有一个状态是合法的,那么dp[i][j]就是可到达的。然后我们还要证明dp[i][j]状态本身是否合法,即判断当前状态的深度是否大于l。最后我们只需要找dp[n][j]的状态中是否有合法的即可。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=110; #define mem(a,b) memset(a,b,sizeof(a)) int T,n,k,l; int d[N],p[2*N]; int dp[N][2*N*N]; void init()//初始化 { for(int i=0;i<=k;i++)p[i]=i;//预处理 for(int i=1;i<k;i++)p[k+i]=k-i; mem(dp,0); for(int i=0;i<2*k;i++)dp[0][i]=1; } int main() { scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&k,&l); init(); for(int i=1;i<=n;i++)scanf("%d",&d[i]); for(int i=1;i<=n;i++) { for(int j=1;j<=2*n*k;j++) { dp[i][j]=max(dp[i][j-1],dp[i-1][j-1]); if(p[j%(2*k)]+d[i]>l)dp[i][j]=0; } } int flag=0; for(int i=0;i<2*n*k;i++) if(dp[n][i]){flag=1;break;} if(flag)printf("Yes\n"); else printf("No\n"); } }
CodeForces - 1384C String Transformation 1
题意:给出两个等长的字串A,B.通过变换,要求A能变成B.变换规则如下:可将A中的一个字母或多个相同的字母变成字典序更大的字母。A若能成功变成B.输出最小变换次数。如不行,输出-1。
思路:并查集简单模板。
AC代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=100010; int T,n,ans; int f[30]; char a[N],b[N]; int getf(int v) { if(f[v]==v)return v; else return f[v]=getf(f[v]); } void merge1(int x,int y) { int t1=getf(x); int t2=getf(y); if(t1!=t2) { ans++; f[t2]=t1; } } int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); ans=0; int flag=0; for(int i=1;i<=28;i++)f[i]=i; scanf("%s%s",a,b); for(int i=0;i<n;i++) if(a[i]>b[i]){flag=1;break;} if(flag){printf("-1\n");continue;} for(int i=0;i<n;i++) merge1(a[i]-'a'+1,b[i]-'a'+1); printf("%d\n",ans); } }