[HDU5807] Keep In Touch

(Keep In Touch):保持联络
(Informatik verbindet dich und mich.) 信息将你我连结?

发现这个方程很容易列出来。
(f[i][j][k]=f[l][m][n])
但是这个方程状态是(n^3)的,转移是(n^3)的,时间复杂度是(O(n^6))的不够优秀。
发现可以牺牲一些空间。
(f[i][j][k][p])表示第一个人在(i),第二个人在(j),第三个人在(k),现在轮到第(p)个人走了。
发现这样的话转移是(n)的,状态是(n^3)的,这样的话就复杂度降到了(n^4),就稳了。。。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int N=55,mod=998244353;
int T,f[N][N][N][3],w[N],K,Q,g[N][N],a,b,c,n,m;
bool pd(int x,int y) {return abs(w[x]-w[y])<=K;}
bool ck(int x,int y,int z) {
	return pd(x,y)&&pd(y,z)&&pd(x,z);
}
int dfs(int x,int y,int z,int r) {
	int &tp=f[x][y][z][r];
	if(tp!=-1) return tp;
	tp=0;
	if(r==1&&ck(x,y,z)) tp=1;
	for(int i=1;i<=n;i++) {
		if(r==1&&g[x][i]) tp=(tp+dfs(i,y,z,2))%mod;
		else if(r==2&&g[y][i]) tp=(tp+dfs(x,i,z,3))%mod;
		else if(r==3&&g[z][i]&&ck(x,y,i)) tp=(tp+dfs(x,y,i,1))%mod;
	}
	return tp;
}
int main() {
	scanf("%d",&T);
	while(T--) {
		memset(f,-1,sizeof f);
		scanf("%d%d%d%d",&n,&m,&K,&Q);
		memset(g,0,sizeof g);
		for(int i=1;i<=n;i++) scanf("%d",&w[i]);
		for(int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),g[x][y]=1;
		while(Q--) scanf("%d%d%d",&a,&b,&c),printf("%d
",dfs(a,b,c,1));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/sdfzhsz/p/9831302.html