HDU5807 Keep In Touch (BestCoder Round #86 D ) 分布式dp

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 50+2;
const int mod = 998244353;
int T,n,m,lim,q,tot,w[N],dp[N][N][N][3],head[N];
struct Edge{
  int v,next;
}edge[N*N/2];
void add(int u,int v){
  edge[tot].v=v;
  edge[tot].next=head[u];
  head[u]=tot++;
}
inline void up(int &x,int y){
  x+=y;if(x>=mod)x-=mod;
}
bool judge(int i,int j){
  return abs(w[i]-w[j])<=lim;
}
int main(){
  scanf("%d",&T);
  while(T--){
    scanf("%d%d%d%d",&n,&m,&lim,&q);
    for(int i=1;i<=n;++i)scanf("%d",&w[i]);
    memset(head,-1,sizeof(head)),tot=0;
    for(int i=0;i<m;++i){
      int u,v;scanf("%d%d",&u,&v);add(v,u);
    }
    memset(dp,0,sizeof(dp));
    for(int i=n;i>0;--i)
     for(int j=n;j>0;--j)
      for(int k=n;k>0;--k){
        if(judge(i,j)&&judge(j,k)&&judge(k,i))
          up(dp[i][j][k][0],1);
        if(dp[i][j][k][0])
          for(int k1=head[i];~k1;k1=edge[k1].next)
            up(dp[edge[k1].v][j][k][1],dp[i][j][k][0]);
        if(dp[i][j][k][1])
          for(int k1=head[j];~k1;k1=edge[k1].next)
            if(!judge(i,edge[k1].v))continue;
            else up(dp[i][edge[k1].v][k][2],dp[i][j][k][1]);
        if(dp[i][j][k][2])
          for(int k1=head[k];~k1;k1=edge[k1].next){
            if(!judge(i,j)||!judge(i,edge[k1].v)||!judge(j,edge[k1].v))
              continue;
            up(dp[i][j][edge[k1].v][0],dp[i][j][k][2]);
          }
      }
     while(q--){
      int x,y,z;
      scanf("%d%d%d",&x,&y,&z);
      printf("%d\n",dp[x][y][z][0]);
     }
  }
  return 0;
}

时间: 2024-08-03 10:31:08

HDU5807 Keep In Touch (BestCoder Round #86 D ) 分布式dp的相关文章

[HDU5807] [BestCoder Round #86 1004] Keep In Touch (DP)

[HDU5807] [BestCoder Round #86 1004] Keep In Touch (DP) 题面 有三个人从一张N个点无重边的有向无环图上的三个点出发,每单位时间,他们分别选择当前点的一条出边走下去.有向无环图点有点权,任意时刻他们所在的三个点两两点权相差不超过K.他们可以在任意三个点同时结束.求合法的路径总数.N≤50. 分析 暴力的做法,设\(dp[i][j][k]\)表示第一个人在i,第二个人在j,第三个人在k的方案数,然后枚举三个人接着到的地方x,y,z,倒推\(dp

HDU 5806 NanoApe Loves Sequence Ⅱ(尺取+思维)——BestCoder Round #86 1003

传送门 NanoApe Loves Sequence Ⅱ Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)Total Submission(s): 514    Accepted Submission(s): 248 Problem Description NanoApe, the Retired Dog, has returned back to prepare for f

BestCoder Round #86 解题报告

A.Price List Sol 求和查询 Code #include<cstdio> #include<algorithm> #include<iostream> using namespace std; typedef long long LL; const int N = 100005; //LL v[N]; inline LL in(LL x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar

HDU5808Price List Strike Back (BestCoder Round #86 E) cdq分治+背包

严格按题解写,看能不能形成sum,只需要分割当前sum怎么由两边组成就好 #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int N = 2e4+100; int f[N][105],g[N][105]

HDU5806 NanoApe Loves Sequence Ⅱ (BestCoder Round #86 C)二分

分析:大于等于m的变成1,否则变成0,预处理前缀和,枚举起点,找到第一个点前缀和大于m即可 找第一个点可以二分可以尺取 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long LL; const int N = 2e5+5; int T,n,m,k,a[N],sum[N]; int mai

HDU5804 Price List (BestCoder Round #86 A)水题

分析:大于总和输出1 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int N = 1e5+5; int ret[N],T,n,m; int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&a

BestCoder Round #86 1001

链接http://acm.hdu.edu.cn/showproblem.php?pid=5804 题意:给你一些商店和他的商品价格,然后给你一个记账本,问你记大了就是1,否则是0 解法:模拟,注意测试数据大小 #include<stdio.h> //#include<bits/stdc++.h> #include<string.h> #include<iostream> #include<math.h> #include<sstream&g

BestCoder Round #86 二,三题题解(尺取法)

第一题太水,跳过了. NanoApe Loves Sequence题目描述:退役狗 NanoApe 滚回去学文化课啦! 在数学课上,NanoApe 心痒痒又玩起了数列.他在纸上随便写了一个长度为 nnn 的数列,他又根据心情随便删了一个数,这样他得到了一个新的数列,然后他计算出了所有相邻两数的差的绝对值的最大值. 他当然知道这个最大值会随着他删了的数改变而改变,所以他想知道假如全部数被删除的概率是相等的话,差的绝对值的最大值的期望是多少. 输入描述 第一行为一个正整数 T,表示数据组数. 每组数

HDU 5805 - NanoApe Loves Sequence (BestCoder Round #86)

先找相邻差值的最大,第二大,第三大 删去端点会减少一个值, 删去其余点会减少两个值,新增一个值,所以新增和现存的最大的值比较一下取最大即可 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 using namespace std; 5 #define LL long long 6 const int N = 100005; 7 int t, n, p1, p2, p3; 8 LL a[N]; 9