题意:
有三个人从一张N个点无重边的有向无环图上的三个点出发,每单位时间,他们分别选择当前点的一条出边走下去。
有向无环图点有点权,任意时刻他们所在的三个点两两点权相差不超过K。
他们可以在任意三个点同时结束。
求合法的路径总数。N≤50。
老师给的例题。
DP、对象独立性。
考虑暴力,f[i][j][k]表示三个人分别在i、j、k,再枚举从f[x][y][z]转移过来,O(n6)。
考虑对象独立性,f[i][j][k][a/b/c]表示三个人分别在i,j,k,再枚举a,b,c,分别表示此时a先走,此时b先走,此时c先走。O(n4)。
Code:
#include<bits/stdc++.h> using namespace std; const int maxn = 55; #define ll long long const int mod = 998244353; ll dp[maxn][maxn][maxn][3]; vector<int> G[maxn]; int n,m,K,q,w[maxn],T; void DP(){ for(int i = n;i>=1;--i) for(int j = n;j>=1;--j) for(int k = n;k>=1;--k){ dp[i][j][k][0] = 1; for(int l = 0;l<G[i].size();++l)dp[i][j][k][0] = (dp[G[i][l]][j][k][2] + dp[i][j][k][0])%mod; for(int l = 0;l<G[j].size();++l)dp[i][j][k][1] = (dp[i][G[j][l]][k][0] + dp[i][j][k][1])%mod; for(int l = 0;l<G[k].size();++l)dp[i][j][k][2] = (dp[i][j][G[k][l]][1] + dp[i][j][k][2])%mod; if(abs(w[i]-w[j]) > K || abs(w[i] - w[k]) > K || abs(w[j]-w[k]) > K)dp[i][j][k][0] = 0; } } int main(){ ios::sync_with_stdio(0); cin>>T; while(T--){ cin>>n>>m>>K>>q; for(int i = 1;i<=n;++i)cin>>w[i]; for(int i = 0;i<maxn;++i)G[i].clear(); for(int i = 1,u,v;i<=m;++i){ cin>>u>>v; G[u].push_back(v); } memset(dp,0,sizeof(dp)); DP(); while(q--){ int a,b,c; cin>>a>>b>>c; cout<<dp[a][b][c][0]<<endl; } } }