hdu 5807 分步dp
有三个人分别在三个位置,每一秒各走一步,三个城市可以联络的要求是两两权值差小于等于K。问有多少种不同的方案,让这三个人可以联络。
dp[x][y][z]表示三个人分别在x,y,z时的答案,直接转移要花n^6,考虑每个人走一步是一种状态,即再加一维表示即将要走的人是哪一个,按照顺序转移0,1,2,0,1,2......所以就能转移。在dp[i][j][k][0]的时候三位步长一样。此时为答案,而如果这一个点是0说明这个状态本身就不能到,所以直接就是0,不可转移。
#include <cstdio> #include <cstring> #include <vector> #include <cmath> #include <stack> #include <cstdlib> #include <queue> #include <map> #include <iostream> #include <algorithm> #define mod 998244353 using namespace std; typedef long long LL; int w[55]; LL dp[55][55][55][4]; vector<int>vec[55]; int check(int i,int j,int k,int K) { if (abs(w[i]-w[j])>K) return 0; if (abs(w[j]-w[k])>K) return 0; if (abs(w[i]-w[k])>K) return 0; return 1; } int main() { int T; scanf ("%d",&T); while (T--) { for (int i=1;i<=50;i++) vec[i].clear(); memset(dp,0,sizeof(dp)); int n,m,K,q; scanf ("%d%d%d%d",&n,&m,&K,&q); for (int i=1;i<=n;i++) { scanf ("%d",&w[i]); } for (int i=1;i<=m;i++) { int u,v; scanf ("%d%d",&u,&v); vec[u].push_back(v); } for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) { for (int k=1;k<=n;k++) { if (check(i,j,k,K)) dp[i][j][k][0]=1; else dp[i][j][k][0]=0; } } } for (int i=n;i>=1;i--) { for (int j=n;j>=1;j--) { for (int k=n;k>=1;k--) { int sz=vec[k].size(); for (int tt=0;tt<sz;tt++) { int to=vec[k][tt]; dp[i][j][k][2]+=dp[i][j][to][0]; dp[i][j][k][2]%=mod; } sz=vec[j].size(); for (int tt=0;tt<sz;tt++) { int to=vec[j][tt]; dp[i][j][k][1]+=dp[i][to][k][2]; dp[i][j][k][1]%=mod; } if (dp[i][j][k][0]==0) continue; sz=vec[i].size(); for (int tt=0;tt<sz;tt++) { int to=vec[i][tt]; dp[i][j][k][0]+=dp[to][j][k][1]; dp[i][j][k][0]%=mod; } } } } while (q--) { int t1,t2,t3; scanf ("%d%d%d",&t1,&t2,&t3); printf ("%lld\n",dp[t1][t2][t3][0]); } } return 0; }