KEYENCE Programming Contest 2021


AB

簽到

C

大力DP,f[i][j]表示走到當前位置的方案數,但問題是無法考慮沒走過路徑的未填位置。不過很好解決,向右走的時候實際方案=原方案數*3^(走過的列下側的未填位置數),向下走的時候實際方案=原方案數*3^(走過的行右側的未填位置數),這樣可以處理掉所有的未填位置。

#include<bits/stdc++.h>
using namespace std;
const int N=5005,mod=998244353;
int n,m,k,pw[N],a[N][N],f[N][N],s[N][N],t[N][N];
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=-1;
    pw[0]=1;for(int i=1;i<=5000;i++)pw[i]=3ll*pw[i-1]%mod;
    for(int i=1,x,y;i<=k;i++)
    {
        char c;scanf("%d%d %c",&x,&y,&c);
        if(c=='X')a[x][y]=0;
        else if(c=='R')a[x][y]=1;
        else a[x][y]=2;
    }
    for(int j=1;j<=m;j++)
    {
        for(int i=n;i;i--)s[i][j]=s[i+1][j]+(a[i][j]==-1);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=m;j;j--)t[i][j]=t[i][j+1]+(a[i][j]==-1);
    }
    f[1][1]=1;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        if(j>1)
        {
            if(!a[i][j-1]||a[i][j-1]==1)f[i][j]=(f[i][j]+1ll*f[i][j-1]*pw[s[i+1][j-1]])%mod;
            else if(a[i][j-1]==-1)f[i][j]=(f[i][j]+2ll*f[i][j-1]*pw[s[i+1][j-1]])%mod;
        }
        if(i>1)
        {
            if(!a[i-1][j]||a[i-1][j]==2)f[i][j]=(f[i][j]+1ll*f[i-1][j]*pw[t[i-1][j+1]])%mod;
            else if(a[i-1][j]==-1)f[i][j]=(f[i][j]+2ll*f[i-1][j]*pw[t[i-1][j+1]])%mod;
        }
    }
    if(a[n][m]==-1)f[n][m]=3ll*f[n][m]%mod;
    printf("%d",f[n][m]);
}
View Code

D

構造能力堪憂於是成功墊底……

很容易發現答案是2^n-1,但就是不會構造……

發現可以將2^(n-1)個人時的答案進行如下復制,假設一個答案是A,則可以復制成AA,AB,其中B與A完全不同,再加上A…AB…B就可達到目的

#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
    scanf("%d",&n);
    printf("%d\n",(1<<n)-1);
    vector<string>a;
    for(int i=1;i<=n;i++)
    {
        vector<string>vec;
        string x="";
        for(int j=1;j<=(1<<i-1);j++)x+='A';
        for(int j=1;j<=(1<<i-1);j++)x+='B';
        vec.push_back(x);
        for(int j=0;j<a.size();j++)
        {
            vec.push_back(a[j]+a[j]);
            string s=a[j];
            for(int k=0;k<s.size();k++)s[k]=s[k]=='A'?'B':'A';
            vec.push_back(a[j]+s);
        }
        a=vec;
    }
    for(int i=0;i<a.size();i++)cout<<a[i]<<endl;
}
View Code

E

考完發現實際上就是DP,f[i][j][k]表示在區間[i,j],取了k個區間外的數的最大值,也是直接DP就行了

#include<bits/stdc++.h>
using namespace std;
const int N=405;
int n,a[N],f[N][N][N];
int dp(int l,int r,int m)
{
    int&ret=f[l][r][m];
    if(ret)return ret;
    int t=0;
    if(l>0||r<=n)
    {
        if(m<n-(r-l-1))
        {
            if(a[l]<a[r])t=max(t,dp(l,r+1,m+1));
            else t=max(t,dp(l-1,r,m+1));
        }
        if(m>=1&&l>=1)t=max(t,a[l]+dp(l-1,r,m-1));
        if(m>=1&&r<=n)t=max(t,a[r]+dp(l,r+1,m-1));
    }
    ret=t;
    return ret;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    a[0]=a[n+1]=-1;
    for(int i=0;i<=n;i++)cout<<dp(i,i+1,1)<<endl;
}
View Code

小號打的 rank=426 performance=1931 rating+=149

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM