Live2D

stars 题解

link

Solution

我们考虑如何判定一个序列是否合法,可以看出的是,我们可以枚举每个排列,如果当前我们构造的 K 失配了,那么我们就把排列中的下一位设为失配的该位值即可。如果存在一个排列使得可以走完整个序列,这个序列即为合法。

我们考虑设 \(f_{i,S}\) 表示的是第 \(i\) 位排列(或是排列的一个前缀)为 \(S\) 能够匹配到的最大长度下的失配点。考虑 \(f_{i,S}\) 以及 \(f_{i+1,S[1:]}\) 的关系。可以发现,对于第一个失配点使得 \(a_{k,S[0]}=a_{i,S[0]}\),那么我们设把 \(S[0]\) 插入 \(k\) 对应的排列位置前面为 \(T\),则有 \(f_{i,S}=\{i,f_{i+1,T}\}\),最大长度显然 \(+1\)。如果找不到,那么我们如果第一个无法匹配的 \(k\) 满足 \(a_{k,S[0]}=a_{i,S[0]}\),那么我们设把 \(S[0]\) 放在最后的排列为 \(T\),则有 \(f_{i,S}=\{i,f_{i+1,T}\}\),最大长度显然 \(+1\),不行的话,则有 \(f_{i,S}=\{i,f_{i+1,S[1:]}\}\)

复杂度我实现的很丑,据说可以做到 \(\Theta(nk!)\),这里代码放上来仅供参考吧。

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define MAXN 100005
#define MAXM 605
#define MAXK 7

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

int N,K,cnt,ind[MAXN],a[MAXN][MAXK],val[MAXN][MAXM],nxt[MAXN][MAXK];

#define poly vector<int>
map <poly,int> mp;
map <int,poly> tur;
poly f[2][MAXM];

signed main(){
	read (N,K);
	for (Int i = 1;i <= N;++ i)
		for (Int j = 1;j <= K;++ j) read (a[i][j]);
	for (Int i = 1;i <= K;++ i) ind[i] = i;
	do{
		poly S;
		for (Int i = 1;i <= K;++ i) S.push_back (ind[i]),tur[++ cnt] = S,mp[S] = cnt;
	}while (next_permutation (ind + 1,ind + K + 1));
	for (Int i = N;i >= 1;-- i)
		for (Int j = 1;j <= K;++ j)	
			if (a[i][j] == a[i + 1][j]) nxt[i][j] = nxt[i + 1][j];
			else nxt[i][j] = i;
	int ans = 0;
	for (Int i = N;i >= 1;-- i){
		for (Int s = 1;s <= cnt;++ s){
			f[i & 1][s].clear (),val[i & 1][s] = 0;
			poly P = tur[s],T = tur[s],H;T.erase (T.begin());
			if (i == N){
				f[i & 1][s].push_back (i),val[i & 1][s] = 1;
				continue;
			}
			if (P.size() == 1){
				f[i & 1][s].push_back (i),val[i & 1][s] = nxt[i][P[0]] - i + 1;
				continue;
			}
			int nt = mp[T],fuc = -1;bool flg = 0;
			for (Int k = 0;k < f[i + 1 & 1][nt].size();++ k){
				int pos = f[i + 1 & 1][nt][k];
				if (a[pos][P[0]] == a[i][P[0]]){
					H.push_back (P[0]),fuc = pos;
					for (Int k1 = k;k1 < T.size();++ k1) H.push_back (T[k1]);
					flg = 1;
					break;
				}
				H.push_back (T[k]);
			}
			if (flg){
				f[i & 1][s].push_back (i);int sht = mp[H];
				for (Int v : f[i + 1 & 1][sht]) if (v != fuc) f[i & 1][s].push_back (v);
				val[i & 1][s] = val[i + 1 & 1][sht] + 1;
			}
			else{
				f[i & 1][s].push_back (i);
				for (Int v : f[i + 1 & 1][nt]) f[i & 1][s].push_back (v);
				int ed = i + val[i + 1 & 1][nt];
				if (a[ed + 1][P[0]] == a[i][P[0]]){
					T.push_back (P[0]);
					val[i & 1][s] = val[i + 1 & 1][mp[T]] + 1;
				}
				else val[i & 1][s] = val[i + 1 & 1][nt] + 1;
			}
		}
		int len = 0;
		for (Int s = 1;s <= cnt;++ s) chkmax (len,val[i & 1][s]);
		ans += len;
	}
	write (ans),putchar ('\n');
	return 0;
}
posted @ 2022-01-25 21:00  Dark_Romance  阅读(39)  评论(0编辑  收藏  举报