2018-2019 ICPC, NEERC, Southern Subregional Contest J-Streets and Avenues in Berhatt [contest/1070]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z591826160/article/details/83271282

J - Streets and Avenues in Berhatt

题面

在这里插入图片描述

思路

简单猜测可知,贡献答案的情况下必然是一组相同的字母被分割在横竖两个方向,其余的都不会贡献答案

因为我们可以用把一组字母尽量用完的方式优先放一横或者一竖,排完之后会有两种情况

  1. 一组剩下一些 那么优先使用其他字母排剩下的方向,如果不够的话再使用剩下的这组
  2. 每一组都是完整的,那么直接随意放,都不会贡献答案

因此,我们可以枚举每一个字母,代表他是最后剩下的那组,并枚举在排第一个方向时用了多少,最后计算一下答案就可以了

复杂度大概是 O ( 26 k ) O(26*k)

代码

const int maxn = 5e5+7;
const int inf  = 0x3f3f3f3f;
const int mod  = 1e9 + 7;
const int none = -1;
const LL linf  = (LL)inf << 32 | inf;

char now[maxn];
bool road[maxn];
ll have[100];
const int sigema=26;
int main(){
    int t;
    rd(t);
    while(t--){
        ll n,m,k;
        rd(n,m,k);
        ll tot=0;
        if(n>m)swap(n,m);
        scanf("%s",now);
        clr(have);
        rep(i,0,k){
            have[now[i]-'A']++;
            tot++;
        }
        ll ans=inf;
        rep(i,0,sigema+1){
            if(!have[i])continue;
            clr(road);
            road[0]=1;
            rep(j,0,sigema+1){
                if(i==j)continue;
                for(ll s=n;s>=0;s--){
                    if(road[s]&&s+have[j]<=n)
                        road[s+have[j]]=1;
                }
            }
            for(ll j=0;j<=have[i];j++){
                if(n-j<0)continue;
                if(!road[n-j])continue;
                if(tot-(n-j)-have[i]>=m){
                    ans=0;continue;
                }
                ll r=m-(tot-(n-j)-have[i]);
                ans=min(ans,j*r);
            }
        }
        printf("%lld\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/z591826160/article/details/83271282