版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z591826160/article/details/83271282
J - Streets and Avenues in Berhatt
题面
思路
简单猜测可知,贡献答案的情况下必然是一组相同的字母被分割在横竖两个方向,其余的都不会贡献答案
因为我们可以用把一组字母尽量用完的方式优先放一横或者一竖,排完之后会有两种情况
- 一组剩下一些 那么优先使用其他字母排剩下的方向,如果不够的话再使用剩下的这组
- 每一组都是完整的,那么直接随意放,都不会贡献答案
因此,我们可以枚举每一个字母,代表他是最后剩下的那组,并枚举在排第一个方向时用了多少,最后计算一下答案就可以了
复杂度大概是
代码
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);
}
}