zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 59 (Rated for Div. 2) DE题解

    Educational Codeforces Round 59 (Rated for Div. 2)

    D. Compression

    题目链接https://codeforces.com/contest/1107/problem/D

    题意:

    给出一个n*(n/4)的矩阵,这个矩阵原本是一些01矩阵,但是现在四个四个储存进二进制里面,现在给出的矩阵为0~9以及A~F,表示0~15。

    然后问这个矩阵能否压缩为一个(n/x)*(n/x)的矩阵,满足原矩阵中大小为x*x的子矩阵所有数都相等(所有子矩阵构成整个原矩阵)。

    题解:

    我想的就是暴力,但题解似乎也是暴力,但题解的做法比我的做法要优美许多。我说说我的吧...

    就是先看看横排能否压缩,找出所有能够压缩的v值,然后将v从大到小进行枚举,来看看列能否照样压缩,能就直接输出答案。

    大体思路就是这样,但我写的代码比较复杂...其实对于将字符解码为二进制,用个二维数组就可以了...

    题解的暴力就是直接几层循环枚举完事。

    下面给出我的代码...

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 5205;
    int n;
    char s[N][N];
    vector <int> vec;
    int main(){
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%s",s[i]);
        for(int i=1;i<=n;i++){
            int flag=1;
            if(n%i!=0) continue ;
            for(int j=0;j<n;j++){
                if(strcmp(s[(j/i)*i],s[j])!=0){
                    flag=0;
                    break ;
                }
            }
            if(flag) vec.push_back(i);
        }
        reverse(vec.begin(),vec.end());
        int flag;
        for(auto v:vec){
            flag=1;
            for(int i=0;i<n;i+=v){
                vector <int> a;
                for(int j=0;j<n/4;j++){
                    char c = s[i][j];
                    int now;
                    if(c>='A' && c<='F') now=c-'A'+10;
                    else now=c-'0';
                    for(int k=3;k>=0;k--){
                        if((1<<k)&now) a.push_back(1);
                        else a.push_back(0);
                    }
                }
                for(int k=0;k<n;k++){
                    if(a[(k/v)*v]-'0'!=a[k]-'0'){
                        flag=0;
                        break ;
                    }
                }
                if(!flag)  break ;
            }
            if(flag){
                cout<<v;
                return 0;
            }
        }
        return 0;
    }
    View Code

    E. Vasya and Binary String

    题目链接:https://codeforces.com/contest/1107/problem/E

    题意:

    给出一个01串,然后对这个串进行压缩,将长度为1,2....n的相同字符进行压缩会得到相应的权值。问怎样压缩可以得到最大的值。

    题解:

    这题考虑dp,因为压缩只有两种情况,要么压缩一个,要么压缩多个,这个压缩多个可以连续,也可以中间有间隔。

    dp(i,j,k)表示起点为i,终点为j,压缩k个和si相同的字符所得到的最大代价。

    转移的话就有两种:

    1.dp(i,j,1)=max{dp(i+1,j,p)}+a[1];

    2.dp(i,j,k)=max{dp(i+1,pos-1,p)}+dp(pos,j,k-1)-ak-1+ak.

    这里面的max我是直接枚举得到最大值,然后dp的过程中枚举pos来进行转移。

    详细见代码吧:

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int N = 105;
    ll a[N];
    ll dp[N][N][N];
    char s[N];
    int n;
    int main(){
        scanf("%d",&n);
        scanf("%s",s+1);
        for(int i=1;i<=n;i++) cin>>a[i];
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++) dp[i][i][1]=a[1];
        for(int i=n-1;i>=1;i--){
            for(int j=i+1;j<=n;j++){
                for(int k=1;k<=j-i;k++)
                dp[i][j][1]=max(dp[i][j][1],dp[i+1][j][k]+a[1]);
                for(int q=i+1;q<=j;q++){
                    ll tmp=0;
                    if(s[q]!=s[i]) continue ;
                    for(int p=1;p<=q-i-1;p++) tmp=max(tmp,dp[i+1][q-1][p]);
                    for(int k=2;k<=j-i+1;k++){
                        if(dp[q][j][k-1]) dp[i][j][k]=max(dp[i][j][k],tmp+dp[q][j][k-1]-a[k-1]+a[k]);
                    }
                }
            }
        }
        ll ans = 0;
        for(int i=1;i<=n;i++) ans=max(ans,dp[1][n][i]);
        cout<<ans;
        return 0;
    }
    View Code
  • 相关阅读:
    Java中-classpath和路径的使用
    总是分不清
    Maven Web项目部署到Tomcat下问题
    一、数据设计规范
    一、入职学习
    一、服务器控件
    WebApiThrottle限流框架
    一、接口的规则
    一、免费API调用
    十、锁
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10352756.html
Copyright © 2011-2022 走看看