Loading

abc 274 d 题解

abc 274 d

题意

给定一个长度为 \(N\) 的序列 \(A\) 和整数 \(x, y\)

请你判断能否放 \(N + 1\) 个点 \(p_0, p_1, \dots, p_{N + 1}\),满足以下条件:

  • \(p_0 = (0, 0)\)

  • \(p_1 = (A_1, 0)\)

  • \(p_{N + 1} = (x, y)\)

  • \(p_i\) 和点 \(p_{i + 1}\) 的距离为 \(A_i\)

  • 线段 \(p_ip_{i + 1}\) 和线段 \(p_{i + 1}p_{i + 2}\) 所形成的夹角为 \(90\) 度。

思路

可以发现,其实题目就是问你有没有一种方法使得 \(p_{N + 1} = (x, y)\),而我们又可以发现,其实 \(x\) 就是由所有 \(A_i \ (i \ 是奇数)\) 凑成的,\(y\) 则是由所有 \(A_i \ (i \ 是偶数)\) 凑成的。

所以我们可以把 \(x, y\) 分开处理,那么就有 \(dp_{0/1, i, j}\) 表示用前 \(i\) 个数中的奇数或偶数是否可以凑出 \(j\)

可以发现,每次都是由 \(i - 1\) 转移到 \(i\) 的,所以可以用滚动数组。

注意:由于坐标有可能是负数,所以需要将坐标偏移。

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 1e3 + 10, M = 2e4 + 10, INF = 1e4;

int n, x, y, a[N], c1 = 1, c2 = 1;
bool dp[2][2][M];

int main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n >> x >> y, x += INF, y += INF;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  dp[0][0][INF + a[1]] = 1;
  for (int i = 3; i <= n; i += 2, c1++) {
    for (int j = 0; j < M; j++) {
      if (j >= a[i]) {
        dp[0][c1 % 2][j] |= dp[0][!(c1 % 2)][j - a[i]];
      }
      if (j + a[i] < M) {
        dp[0][c1 % 2][j] |= dp[0][!(c1 % 2)][j + a[i]];
      }
    }
    fill(dp[0][!(c1 % 2)], dp[0][!(c1 % 2)] + M, 0);
  }
  dp[1][0][INF] = 1;
  for (int i = 2; i <= n; i += 2, c2++) {
    for (int j = 0; j < M; j++) {
      if (j >= a[i]) {
        dp[1][c2 % 2][j] |= dp[1][!(c2 % 2)][j - a[i]];
      }
      if (j + a[i] < M) {
        dp[1][c2 % 2][j] |= dp[1][!(c2 % 2)][j + a[i]];
      }
    }
    fill(dp[1][!(c2 % 2)], dp[1][!(c2 % 2)] + M, 0);
  }
  cout << (dp[0][(c1 - 1) % 2][x] && dp[1][(c2 - 1) % 2][y] ? "Yes" : "No");
  return 0;
}
posted @ 2023-06-02 15:44  chengning0909  阅读(5)  评论(0编辑  收藏  举报