1. 程式人生 > >Educational Codeforces Round 59 (Rated for Div. 2) DE題解

Educational Codeforces Round 59 (Rated for Div. 2) DE題解

我想 def isp ons opened lag sca view %d

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

Educational Codeforces Round 59 (Rated for Div. 2) DE題解