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\n",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\times t-1\)个转折点,设\(dp[x][y][t]\)为当最后一点落在\((x,y)\)上时,出现\(t\)个转折点的总数。那么对于当前点有两种情况,他的前一个点到当前点要么高度比他大,要么比他小。

若当前点\((x,y)\)之前出现了\(t\)个转折点,若\(t\)为偶数,也就是说只要前一个点落点在当前点的下方,当前状态要想保持任然只出现偶数\(t\)个转折点的情况,则
\[dp[x][y][t]=\sum (dp[x-1][h][t])(1\le h<y)\]

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

\[dp[x][y][t+1]=\sum (dp[x][h][t])(y<h\le 4)\]
\(t\)为奇数时,同样的,

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

\[dp[x][y][t+1]=\sum (dp[x-1][h][t])(1\le 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;
}

猜你喜欢

转载自www.cnblogs.com/cbyyc/p/11487755.html