ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Warp(DP)

2022-09-05 00:33:42  阅读:160  来源: 互联网

标签:传送 int res ll Warp leq include DP


题意

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

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

  • 从当前位置\((X,Y)\)移动到\((X+A,Y+B)\)
  • 从当前位置\((X,Y)\)移动到\((X+C,Y+D)\)
  • 从当前位置\((X,Y)\)移动到\((X+E,Y+F)\)

有\(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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有