1. 程式人生 > >2018-2019 ICPC, NEERC, Southern Subregional Contest J-Streets and Avenues in Berhatt [contest/1070]

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

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); } }