ABC 358


反思

做出了A,B,D题,D题是前几天cf的一道启发,c题没做出来,需要反思,因为暴力解法完全能过,当时没考虑,一心想用bfs+状压
e题确实没想到dp,g题倒是想到dp了,但数据量太大不止如何优化。

补题

c题

在这里插入图片描述
这题数据范围不大,纯暴力
但也需要状态压缩的技巧

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N=200002;
int d[11];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m;
    int ans=11;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        string s;
        cin>>s;
        for(char c:s){
            d[i]=(d[i]<<1)+(c=='x');
        }
    }
    for(int i=0;i<(1<<n);i++){
        int tmp=(1<<m)-1;
        int cnt=0;
        for(int j=0;j<n;j++){
            if((i>>j)&1){
                cnt++;
                tmp&=d[j];
            }
        }
        if(!tmp)ans=min(ans,cnt);
    }
    cout<<ans<<endl;

    return 0;
}

E题

在这里插入图片描述
dp解法
dp[i][j]含义:只考虑第1~i个字母,规定长度为j,组成的符合条件的字符串数
状态转移方程:dp[i+1][j+k]=d[i][j]+组合数C(j+k,k)

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N=123214;
int mod=998244353;
int sum[27];
ll dp[30][2000];
ll cc[1002][1002];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int k;
    int c[30];
    cin>>k;
    for(int i=1;i<=26;i++){
        cin>>c[i];
        sum[i]=c[i]+sum[i-1];
    }
    for(int i=0;i<=k;i++){
        cc[i][0]=1;
        for(int j=1;j<=i;j++){
            cc[i][j]=(cc[i-1][j-1]+cc[i-1][j])%mod;
        }
    }
    for(int i=0;i<=c[1];i++){
        dp[1][i]=1;
    }
    for(int i=2;i<=26;i++){
        dp[i][0]=1;
        for(int j=1;j<=min(sum[i],k);j++){
            for(int m=max(0,j-c[i]);m<=min(j,sum[i-1]);m++){
                dp[i][j]=(dp[i][j]+(dp[i-1][m]*1ll*cc[j][m])%mod)%mod;
            }
        }
    }
    ll ans=0;
    for(int i=1;i<=k;i++)ans=(ans+dp[26][i])%mod;
    cout<<ans<<endl;
    return 0;
}

F题

真的不想补了,求放过~~

G题

在这里插入图片描述

dp解法很显然,但是k<=1e9,若全部遍历会因太大导致dp数组开辟不了
所以需要发现:最佳路径一定是无重复路径,且最终停留于某一点
故最多在n*m步后,它一定会停留在某一点不走

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N = 123214;
ll dp[3003][51][51];
int A[51][51];
int dx[]={0,0,1,0,-1};
int dy[]={0,1,0,-1,0};
ll inf=1000000000000000001LL;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int h,w,x,y,k1;
    int max1=0;
    cin>>h>>w>>k1>>x>>y;
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            cin>>A[i][j];
            max1=max(max1,A[i][j]);
        }
    }
    for(int i=1;i<=h;i++)
    {
        for(int j=1;j<=w;j++)
        {
            for(int t=0;t<=min(k1,2500);t++)dp[t][i][j]=-inf;
        }
    }
    for(int i=0;i<5;i++){
        int a=x+dx[i],b=y+dy[i];
        if(a>=1 && a<=h && b>=1 && b<=w){
            dp[1][a][b]=A[a][b];
        }
    }
    for(int i=1;i<min(2500,k1);i++){
        for(int j=1;j<=h;j++){
            for(int k=1;k<=w;k++){
                if(dp[i][j][k]<0)continue;
                for(int d=0;d<5;d++){
                    int a=j+dx[d],b=k+dy[d];
                    if(a>=1 && a<=h && b>=1 && b<=w)dp[i+1][a][b]=max(dp[i+1][a][b],dp[i][j][k]+A[a][b]);
                }
            }
        }
    }
    ll ans=0;
    int t=min(2500,k1);
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            ans=max(ans,dp[t][i][j]+A[i][j]*1ll*(k1-t));
        }
    }
    cout<<ans<<endl;
    return 0;
}

总结

菜就多练~~!!!

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值