其他分享
首页 > 其他分享> > Warp(DP)

Warp(DP)

作者:互联网

题意

有一个人站在二维平面的原点处。

他将会进行\(N\)次传送,每次传送他可以做如下三种移动中的一种:

有\(M\)个障碍物,分别位于\((X_1,Y_1),\dots, (X_M, Y_M)\),他不能传送到这些点上。

问经过\(N\)次传送,会产生多少条路径。

题目链接:https://atcoder.jp/contests/abc265/tasks/abc265_e

数据范围

\(1 \leq N \leq 300\)
\(0 \leq M \leq 10^5\)
\(-10^9 \leq A,B,C,D,E,F \leq 10^9\)

思路

这里提供两种思路。两种思路都是使用DP。

第一种思路,令\(f(n, x, y)\)表示\(n\)次传送,终点是\((x,y)\)的路径条数,转移方程显然。但是坐标范围太大,真的可以这样做吗?其实能到达的点的数量并不多。我们可以分析一下,三种传送方式的个数决定了终点,并且在给定总次数的情况下,固定前两种传送方式的个数,第三种传送方式的个数也固定了。因此,传送到的点数其实只有\(O(N^2)\)。在实际编写代码的过程中,不能直接使用数组进行转移,可以使用map来做。

第二种思路,令\(f(n,x,y)\)表示\(n\)次传送,其中第一种传送使用次数为\(x\),第二种传送使用次数为\(y\),可以产生多少条路径。转移方程显然。

代码

思路1

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> pii;

const int N = 310, M = 100010, mod = 998244353;

int n, m;
ll dx[5], dy[5];
map<pii, ll> f;
set<pii> st;

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 0; i < 3; i ++) {
        scanf("%lld%lld", &dx[i], &dy[i]);
    }
    for(int i = 1; i <= m; i ++) {
        ll x, y;
        scanf("%lld%lld", &x, &y);
        st.insert({x, y});
    }
    f[{0, 0}] = 1;
    for(int i = 0; i < n; i ++) {
        map<pii, ll> g;
        for(auto p : f) {
            ll x = p.first.first, y = p.first.second, val = p.second;
            for(int j = 0; j < 3; j ++) {
                ll tx = x + dx[j], ty = y + dy[j];
                if(st.find({tx, ty}) != st.end()) continue;
                g[{tx, ty}] = (g[{tx, ty}] + val) % mod;
            }
        }
        swap(f, g);
    }
    ll res = 0;
    for(auto p : f) {
        res = (res + p.second) % mod;
    }
    printf("%lld\n", res);
    return 0;
}

思路2

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> pii;

const int N = 310, M = 100010, mod = 998244353;

int n, m;
ll dx[5], dy[5];
ll f[N][N][N];
map<pii, bool> st;

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 0; i < 3; i ++) {
        scanf("%lld%lld", &dx[i], &dy[i]);
    }
    for(int i = 1; i <= m; i ++) {
        ll x, y;
        scanf("%lld%lld", &x, &y);
        st[{x, y}] = true;
    }
    f[0][0][0] = 1;
    for(ll i = 1; i <= n; i ++) {
        for(ll j = 0; j <= i; j ++) {
            for(ll k = 0; k <= i; k ++) {
                ll z = i - j - k;
                if(z < 0) continue;
                ll X = j * dx[0] + k * dx[1] + z * dx[2];
                ll Y = j * dy[0] + k * dy[1] + z * dy[2];
                if(st.count({X, Y})) {
                    f[i][j][k] = 0;
                    continue;
                }
                f[i][j][k] = (f[i - 1][j][k] + f[i - 1][j - 1][k]) % mod;
                f[i][j][k] = (f[i][j][k] + f[i - 1][j][k - 1]) % mod;
            }
        }
    }
    ll res = 0;
    for(int i = 0; i <= n; i ++) {
        for(int j = 0; j <= n; j ++) {
            if(i + j > n) continue;
            res = (res + f[n][i][j]) % mod;
        }
    }
    printf("%lld\n", res);
    return 0;
}

标签:传送,int,res,ll,Warp,leq,include,DP
来源: https://www.cnblogs.com/miraclepbc/p/16656632.html