CodeForces 14 题解

A

模拟题

思路

先找到*,再找出边界,最后输出。然后找边界的最小值应该赋一个极大值

Code

char ch[101][101],c;
int p,q,x,y;
signed main(){
    int n=read(),m=read();
	p=x=0x3f;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++){
		cin>>c;
		ch[i][j]=c;
		if(c=='*'){
			if(i<=p) p=i;
			if(j<=x) x=j;
			if(i>=q) q=i;
			if(j>=y) y=j;
		}
	}
	for(int i=p;i<=q;i++){
		for(int j=x;j<=y;j++)
		printf("%c",ch[i][j]);
		puts("");
	}
    return 0;
}

B

思路

暴力枚举即可

Code


int a[5005],ans=inf;
signed main(){
    int n=read(),x0=read();
	for(int i=0;i<n;i++){
		int x=read(),y=read();
		if(x>y) swap(x,y);//ai可能大于bi
		for(int j=x;j<=y;j++){
			a[j]++;//枚举点
			if(a[j]==n)
				if(abs(j-x0)<ans) ans=abs(j-x0);//找最大距离
		}	
	} 
	if(ans==inf) ans=-1;
	printf("%d
",ans);
    return 0;
}

C

思路

对于每个点 看是否只有一个点和它是相同的
如果是 看输入的 4 条边是否 是 其中两条和 (x) 轴平行 另两条和 (y) 轴平行

Code

struct Node{
	int x,y;
}p[10];
signed main(){
    for(int i=0;i<8;i++) scanf("%d%d",&p[i].x,&p[i].y);
    bool flag=true;
    for(int i=0;i<8;i++){
    	int cnt=0;
      	for(int j=0;j<8;j++ ) 
        if(p[i].x==p[j].x&&p[i].y==p[j].y) cnt++;
      	if(cnt!=2){flag=false;break;}
    }
    if(flag==false) return puts("NO"),0;
    int tx=0,ty=0;
    for(int i=0;i<4;i++){
      if(p[i*2].x==p[i*2+1].x&&p[i*2].y!=p[i*2+1].y) tx++;
      if(p[i*2].x!=p[i*2+1].x&&p[i*2].y==p[i*2+1].y) ty++;
    }
    if(!(tx==2&&ty==2)) flag=false;
    if(flag) printf("YES");
    else printf("NO");
  	return 0;
}

D

求树的直径,这里用的邻接矩阵,(dfs)

思路

(n)个点,(n-1)条无向边求这个图中最长的两条不相交的链长度,
因为这里只有(n-1)条边,所以这一定不会存在环,
所以我们可以枚举每一条边,用这条边把图分成两部分,
求各自部分的树的直径,然后乘积,
(dfs)的时候记录最长和次长的树链长度

int dep,n,ch[maxn][maxn];//邻接矩阵 
inline int dfs(int x,int y){
	int maxx=0,maxx1=0,maxpath=0;
	for(int i=1;i<=n;i++){
		if(ch[i][x]&&i!=y){
			int z=dfs(i,x);
			if(maxpath<z) maxpath=z;
			if(maxx<dep){
				maxx1=maxx;
				maxx=dep;
			}
			else if(maxx1<dep) maxx1=dep;
		}
	}
	if(maxpath<maxx+maxx1) maxpath=maxx1+maxx;
	dep=maxx+1;
	return maxpath;
}
signed main(){
	n=read();
	for(int i=1;i<n;i++){
		int x=read(),y=read();
		ch[x][y]=ch[y][x]=1;
	}
	int ans=-1;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	if(ch[i][j]){
		int a=dfs(i,j);
		int b=dfs(j,i);
		ans=max(ans,a*b);
	}
	printf("%d",ans);
	return 0;
}

E

(DP)
但可以优化到三维

题意:

给你一个数(N),从(1)(N)形成(t)个波峰和(t-1)个波谷,总共有多少种情况。

思路:

将问题分解为求(2 imes t-1)个转折点,设(dp[x][y][t])为当最后一点落在((x,y))上时,出现(t)个转折点的总数。那么对于当前点有两种情况,他的前一个点到当前点要么高度比他大,要么比他小。

若当前点((x,y))之前出现了(t)个转折点,若(t)为偶数,也就是说只要前一个点落点在当前点的下方,当前状态要想保持任然只出现偶数(t)个转折点的情况,则

[dp[x][y][t]=sum (dp[x-1][h][t])(1le h<y) ]

同时只要前一个点落在当前点的上方,都可以达到

[dp[x][y][t+1]=sum (dp[x][h][t])(y<hle 4) ]

(t)为奇数时,同样的,

[dp[x][y][t]=sum (dp[x-1][h][t])(y<hle 4); ]

[dp[x][y][t+1]=sum (dp[x-1][h][t])(1le h<y) ]

当然,对于最开始的转折点一定是上升的。

Code

int dp[25][5][25];
signed main(){
	for(int i=1;i<=3;i++) dp[1][i][0]=1;
	for(int x=2;x<22;x++)
	for(int y=1;y<=4;y++)
	for(int t=0;t<21;t++)
	for(int h=1;h<=4;h++){
		if(x==2){
            if(y>h){
            if(t%2) dp[2][y][t+1]+=dp[1][h][t];
            else dp[2][y][t]+=dp[1][h][t];
        	}
        }
        else{
            if(t%2){
            if(h>y) dp[x][y][t]+=dp[x-1][h][t];
            else if(h<y) dp[x][y][t+1]+=dp[x-1][h][t];
            }
            else{
            if(h<y) dp[x][y][t]+=dp[x-1][h][t];
            else if(h>y) dp[x][y][t+1]+=dp[x-1][h][t];
            }
        }
	}
	int n=read(),t=read();
	if(t*2+1>n||n>6*t+1) return puts("0"),0;
	int ans=0;
	for(int i=1;i<=4;i++)
	ans+=dp[n][i][2*t-1];
	printf("%d",ans); 
	return 0;
}
原文地址:https://www.cnblogs.com/cbyyc/p/11487755.html