HDU 5807 Keep In Touch DP

Keep In Touch


Problem Description

There are n cities numbered with successive integers from 1 to n in Byteland. Also, there are m one-way roads connecting the cities. The starting point of the i-th road is ui while the ending point is vi.

There are 3 spies : 007, 008 and 009. They are going to start q secret missions.

During each mission, they may be in three different cities, and they contact each other using interphones. The radio frequency of the i-th city is wi. Two spies can contact with each other if and only if the absolute value of the difference of radio frequency between the cities where they are in is no more than K. At each moment, three spies must choose a road and go to another city. The time for traveling each road is only a unit of time.

They can choose to end the mission in any city, even in the city where they started the mission. But they are not allowed to end mission in the middle of the roads. Now they want to know, for each mission whose start points are given, what‘s the number of possible ways, during which they can contact with each other at any moment when they are not on roads?

Two ways are considered different if and only if there exists at least one spy at different cities on the same moment.

Note : 3 spies must end the mission at the same time.

Input

The first line of the input contains an integer T (1≤T≤10), denoting the number of test cases.

In each test case, the first line of the input contains four integers n (1≤n≤50),m(0≤m≤n(n−1)2),K(0≤K≤109),q(1≤q≤125000), denoting the number of cities, the number of roads, the upper limit of interphone and the number of missions.

The second line of the input contains n integers w1,w2,...,wn (1≤wi≤109), denoting the radio frequency of the i-th city.

Each of the next m lines contains two integers ui,vi (1≤ui<vi≤n), denoting an one-way road. There are no multiple edges in the graph.

Each of the next q lines contains three integers x,y,z(1≤x,y,z≤n), denoting the starting point of the three spies in each mission. You can assume that there are at least one possible way in each mission.

Output

For each test case, print q lines with one integer per line. For each mission, print the number of possible ways modulo 998244353.

Sample Input

1
4 4 2 10
8 8 4 1
1 3
1 4
2 3
2 4
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
3 3 3
4 4 4

Sample Output

3
3
3
3
3
3
3
3
1
1

题意:

  BestCoder Round #86 1004 中文题面

题解

  首先dp[i][j][k] a,b,c分别在i,j,k三个点得答案

  这样暴力DP 在完全图下复杂度 O(N^6)

  于是考虑加维,设f[i][j][k][now]

   f[i][j][k][now]表示三个人分别在i,j,k时,目前准备走now这个人的方案数,那么转移复杂度就降低到了O(n^4)

  

#include<bits/stdc++.h>
using namespace std;

#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair

typedef long long LL;
const long long INF = 1e18;
const double Pi = acos(-1.0);
const int N = 50+10, M = 5e5+11, inf = 2e9, mod = 998244353;

LL dp[N][N][N][3];
vector<int > G[N];
int n,m,K,q,w[N],T;
void solve() {
        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;//dp[i][j][k][1] = dp[i][j][k][2] = 0;
                for(int ii = 0; ii < G[i].size(); ++ii) dp[i][j][k][0] = (dp[G[i][ii]][j][k][2] + dp[i][j][k][0]) % mod;
                for(int ii = 0; ii < G[j].size(); ++ii) dp[i][j][k][1] = (dp[i][G[j][ii]][k][0] + dp[i][j][k][1]) % mod;
                for(int ii = 0; ii < G[k].size(); ++ii) dp[i][j][k][2] = (dp[i][j][G[k][ii]][1] + dp[i][j][k][2]) % mod;
                if(abs(w[i] - w[j]) > K || abs(w[i] - w[k]) > K || abs(w[k] - w[j]) > K) dp[i][j][k][0] = 0;
            }
        }
}
int main () {
        scanf("%d",&T);
        while(T--) {
            scanf("%d%d%d%d",&n,&m,&K,&q);
            for(int i = 1; i <= n; ++i) scanf("%d",&w[i]);
            for(int i = 0; i < N; ++i) G[i].clear();
            for(int i = 1; i <= m; ++i) {
                    int u,v;
                    scanf("%d%d",&u,&v);
                    G[u].push_back(v);
            }
            memset(dp,0,sizeof(dp));
            solve();
            while(q--) {
                    int a,b,c;
                    scanf("%d%d%d",&a,&b,&c);
                    printf("%I64d\n",dp[a][b][c][0]);
            }
        }
}
时间: 2024-10-11 01:34:41

HDU 5807 Keep In Touch DP的相关文章

HDU 5807 Keep In Touch

加维降复杂度 #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #i

hdu 3555 Bomb(数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 题目大意:就是给你一个数n,判断从0到n有多少个数含有数字49...... 是不是觉得跟hdu2089很相似呀... 思路:跟hdu2089一样的,注意给出的数比较大,所以这儿用__int64  .... code: #include<cstdio> #include<iostream> #include<cstring> #include<algorithm&

HDU 1231 最大连续子序列 DP题解

典型的DP题目,增加一个额外要求,输出子序列的开始和结尾的数值. 增加一个记录方法,nothing special. 记录最终ans的时候,同时记录开始和结尾下标: 更新当前最大值sum的时候,更新开始节点. const int MAX_N = 10001; long long arr[MAX_N]; int N, sta, end; long long getMaxSubs() { long long sum = 0, ans = LLONG_MIN; int ts = 0; for (int

[ACM] hdu 2089 不要62(数位Dp)

不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 19043    Accepted Submission(s): 6442 Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就

HDU 4901 The Romantic Hero(DP)

HDU 4901 The Romantic Hero 题目链接 题意:给定一个序列,要求找一个分界点,然后左边选一些数异或和,和右边选一些数且和相等,问有几种方法 思路:dp,从左往右和从右往左dp,求出异或和且的个数,然后找一个分界点,使得一边必须在分界点上,一边随意,然后根据乘法原理和加法原理计算 代码: #include <cstdio> #include <cstring> typedef __int64 ll; const int N = 1024; const int

HDU 1160 FatMouse&#39;s Speed DP题解

本题就先排序老鼠的重量,然后查找老鼠的速度的最长递增子序列,不过因为需要按原来的标号输出,故此需要使用struct把三个信息打包起来. 查找最长递增子序列使用动态规划法,基本的一维动态规划法了. 记录路径:只需要记录后继标号,就可以逐个输出了. #include <stdio.h> #include <algorithm> using namespace std; const int MAX_N = 1005; struct MouseSpeed { int id, w, s; b

HDU 2089 不要62(数位DP,三种姿势)

HDU 2089 不要62(数位DP,三种姿势) ACM 题目地址:HDU 2089 题意: 中文题意,不解释. 分析: 100w的数据,暴力打表能过 先初始化dp数组,表示前i位的三种情况,再进行推算 直接dfs,一遍搜一变记录,可能有不饥渴的全部算和饥渴的部分算情况,记录只能记录全部算(推荐看∑大的详细题解Orz) 代码: 1. 暴力 (以前写的) /* * Author: illuz <iilluzen[at]gmail.com> * File: 2089_bf.cpp * Create

HDU 2084 数塔 --- 入门DP

HDU 2084 数塔 从下往上递推,状态转移方程 dp[i][j] = max( dp[i+1][j], dp[i+1][j+1]) + a[i][j]; /* HDU 2084 数塔 --- 入门DP */ #include <cstdio> const int N = 105; int dp[N][N]; int MAX(int a, int b){ return a > b ? a : b; } int main() { #ifdef _LOCAL freopen("D

hdu 1160 FatMouse&#39;s Speed(dp)

http://acm.hdu.edu.cn/showproblem.php?pid=1160 #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; struct Node { int w,s,id,fa; }; Node mice[1000+10]; int dp[100