UVA 1625 Color Length

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

猜你喜欢

转载自www.cnblogs.com/sahdsg/p/10561078.html