HDU5807 Keep In Touch DP
1 // HDU5807 Keep In Touch DP 2 // 思路:直接暴力是O(n^6).所以要优化一下 3 // dp[i][j][k][0]:当前点i j k的方案数 4 // dp[i][j][k][1]:j在当前时刻,i k还在上次 5 // dp[i][j][k][2]:j k在当前时刻,i还在上次 6 // 那么就可以转移了 本题u<v 所以转移的时候从大到小 从后往前 7 8 #include <bits/stdc++.h> 9 using namespace std; 10 #define clc(a,b) memset(a,b,sizeof(a)) 11 #define inf 0x3f3f3f3f 12 #define lson l,mid,rt<<1 13 #define rson mid+1,r,rt<<1|1 14 const int N = 300010; 15 const int MOD = 998244353; 16 #define LL long long 17 double const pi = acos(-1); 18 void fre() {freopen("in.txt","r",stdin);} 19 20 int n,m,c,q; 21 int w[55]; 22 int g[55][55]; 23 int dp[55][55][55][3]; 24 25 int check(int a,int b,int c){ 26 return max(abs(a-b),max(abs(b-c),abs(a-c))); 27 } 28 void DP(){ 29 for(int i=n;i>=1;i--){ 30 for(int j=n;j>=1;j--){ 31 for(int k=n;k>=1;k--){ 32 dp[i][j][k][0]=1,dp[i][j][k][1]=dp[i][j][k][2]=0; 33 for(int h=i+1;h<=n;h++){ 34 if(g[h][i]) dp[i][j][k][0]=(dp[i][j][k][0]+dp[h][j][k][2])%MOD; 35 } 36 for(int h=j+1;h<=n;h++){ 37 if(g[h][j]) dp[i][j][k][1]=(dp[i][h][k][0]+dp[i][j][k][1])%MOD; 38 } 39 for(int h=k+1;h<=n;h++){ 40 if(g[h][k]) dp[i][j][k][2]=(dp[i][j][h][1]+dp[i][j][k][2])%MOD; 41 } 42 if(check(w[i],w[j],w[k])>c) dp[i][j][k][0]=0; 43 } 44 } 45 } 46 } 47 48 int main(){ 49 int T; 50 scanf("%d",&T); 51 while(T--){ 52 scanf("%d%d%d%d",&n,&m,&c,&q); 53 for(int i=1;i<=n;i++) scanf("%d",&w[i]); 54 clc(g,0); 55 clc(dp,0); 56 for(int i=1;i<=m;i++) { 57 int u,v; 58 scanf("%d%d",&u,&v); 59 g[v][u]=1; 60 } 61 DP(); 62 while(q--){ 63 int u,v,z; 64 scanf("%d%d%d",&u,&v,&z); 65 printf("%d\n",dp[u][v][z][0]); 66 } 67 } 68 return 0; 69 }