[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\n",dfs(a,b,c,1));
	}
	return 0;
}
posted @ 2018-10-22 17:23  SWHsz  阅读(223)  评论(0编辑  收藏  举报