P7997 [WFOI - 01] 刷题(bfs)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P7997 [WFOI - 01] 刷题(bfs)相关的知识,希望对你有一定的参考价值。
P7997 [WFOI - 01] 刷题(bfs)
容易知道到达的值范围是 [ 0 , 2 × m x ) [0,2\\times mx) [0,2×mx)
考虑把每个值当作点,然后拆点。
分别表示奇数次到达 [ 0 , 4000 ) [0,4000) [0,4000)和偶数次到达的点 [ 4000 , 8000 ) [4000,8000) [4000,8000)
建边
void add(int u,int v)
e[++cnt]=v+4000,h[u],h[u]=cnt;
e[++cnt]=v,h[u+4000],h[u+4000]=cnt;
for(int i=0;i<mx;i++)
rep(j,1,n)
if(i>=a[j]) add(i,i-a[j]);
else add(i,i+a[j]);
然后从 4000 4000 4000出发,跑最短路。
代码如下:
// Problem: P7997 [WFOI - 01] 刷题 (problem)
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P7997
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// Date: 2022-01-07 12:06:31
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=2e3+5,M=1e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = 402653189,805306457,1610612741,998244353;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(nullptr)
void Print(int *a,int n)
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\\n",a[n]);
template <typename T> //x=max(x,y) x=min(x,y)
void cmx(T &x,T y)
if(x<y) x=y;
template <typename T>
void cmn(T &x,T y)
if(x>y) x=y;
int h[M],cnt;
struct node
int to,nt;
e[M*2000];
void add(int u,int v)
e[++cnt]=v+4000,h[u],h[u]=cnt;
e[++cnt]=v,h[u+4000],h[u+4000]=cnt;
ll f[M];
int a[N],mx;
//4000*2000*2
int main()
int n,t;
scanf("%d%d",&n,&t);
rep(i,1,n) scanf("%d",&a[i]),cmx(mx,a[i]);
mx<<=1;
for(int i=0;i<mx;i++)
rep(j,1,n)
if(i>=a[j]) add(i,i-a[j]);
else add(i,i+a[j]);
mst(f,0x3f);
f[4000] = 0;
queue<int>q;q.push(4000);
while(!q.empty())
int u = q.front();q.pop();
for(int i=h[u];i;i=e[i].nt)
int v = e[i].to;
if(f[v]>f[u]+1)
f[v] = f[u] + 1;
q.push(v);
while(t--)
ll x;scanf("%lld",&x);
//printf("x=%lld\\n",x);
if(x&1)
for(int i=3999;i>=0;--i)
if(f[i]<=x)
printf("%d\\n",i);break;
else
for(int i=7999;i>=4000;--i)
if(f[i]<=x)
printf("%d\\n",i-4000);break;
return 0;
;
以上是关于P7997 [WFOI - 01] 刷题(bfs)的主要内容,如果未能解决你的问题,请参考以下文章