https://vjudge.net/problem/UVA-1625
题目
输入两个长度分别为 $n$ 和 $m$($n,m\leqslant 5000$)的颜色序列,要求按顺序合并成同一个序列,即每次可以把一个序列开头的颜色放到新序列的尾部。
例如,两个颜色序列GBBY和YRRGB,至少有两种合并结果:GBYBRYRGB和YRRGGBBYB。对于每种颜色$c$来说,其跨度$L(c)$等于最大位置和最小位置之差。
你的任务是找一种合并方式,使得所有$L(c)$的总和最小。
题解
刚开始想因为颜色只有26种,于是直接用二进制压位……
心想最后一个位置以后再说,先直接用异或,如果得到结果比样例小再继续修改= =
后来发现一个大,一个小,改了很久还不知道是为什么……
然后猛然醒悟= =
如果没有蓝色部分,那么会偏小,如果有蓝色部分,会多算深蓝色的部分(这种问题也要纠结几个小时= =)
所以还是老老实实判断是不是最后一个元素吧
因为继续用了压位,所以比标程慢了260ms(0ms->260ms,还是丢人)
AC代码
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") #include<bits/stdc++.h> using namespace std; #define REP(r,x,y) for(register int r=(x); r<(y); r++) #define PER(r,x,y) for(register int r=(x); r>(y); r--) #define REPE(r,x,y) for(register int r=(x); r<=(y); r++) #define PERE(r,x,y) for(register int r=(x); r>=(y); r--) #ifdef sahdsg #define DBG(...) printf(__VA_ARGS__) #else #define DBG(...) (void)0 #endif #define MAXN 1007 char stra[MAXN]; char strb[MAXN]; int dp[MAXN][MAXN]; int cosx[MAXN][MAXN]; int e1[MAXN], e2[MAXN]; inline int getone(int k) { k = (k&0x55555555)+((k>>1)&0x55555555); k = (k&0x33333333)+((k>>2)&0x33333333); k = (k&0x0F0F0F0F)+((k>>4)&0x0F0F0F0F); k = (k&0x00FF00FF)+((k>>8)&0x00FF00FF); k = (k&0x0000FFFF)+((k>>16)&0x0000FFFF); return k; } inline int cost(int i, int j) { return getone(cosx[i][j]); } int main() { #ifdef sahdsg freopen("in.txt", "r", stdin); #endif int n; scanf("%d", &n); while(0<n--) { scanf("%s%s", stra, strb); int l1=strlen(stra), l2=strlen(strb); char *p1=stra, *p2=strb; memset(e1,0,sizeof e1); memset(e2,0,sizeof e2); REP(i,0,l1) { e1[p1[i]-'A'] = i+1; } REP(j,0,l2) { e2[p2[j]-'A'] = j+1; } memset(dp,0x3f,sizeof dp); memset(cosx,0x7f,sizeof cosx); cosx[0][0]=0; dp[0][0]=0; REPE(i,0,l1) { REPE(j,0,l2) { if(i) { int nk = cosx[i-1][j]|(1<<(p1[i-1]-'A')); int nv = dp[i-1][j]+cost(i-1,j); if(i==e1[p1[i-1]-'A'] && j>=e2[p1[i-1]-'A']) nk = nk ^ (1<<(p1[i-1]-'A')); if(dp[i][j] > nv || (dp[i][j]==nv && cost(i,j)>getone(nk))) { cosx[i][j] = nk; dp[i][j] = nv; } } if(j) { int nk = cosx[i][j-1]|(1<<(p2[j-1]-'A')); int nv = dp[i][j-1]+cost(i,j-1); if(j==e2[p2[j-1]-'A'] && i>=e1[p2[j-1]-'A']) nk = nk ^ (1<<(p2[j-1]-'A')); if(dp[i][j] > nv || (dp[i][j]==nv && cost(i,j)>getone(nk))) { cosx[i][j] = nk; dp[i][j] = nv; } } } } printf("%d\n", dp[l1][l2]); } return 0; }