D
思路:创建set集合,从出现的已有前缀和中找到是否有当前前缀和加p,q,r和的存在;
2种方法:1、set.find;存在则不等于空,即不等于s.end();2、二分,查找,鉴于数据过大;选择二分;
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
#define ll long long
ll a[N];
ll n,p,q,r,ans=0;
set<ll>s({0});
int main()
{
cin>>n>>p>>q>>r;
for(int i=0;i<n;i++)
{
cin>>a[i];
ans+=a[i];
s.insert(ans);
}
for(auto x:s)
{
if(s.find(x+p)!=s.end()&&s.find(x+p+q)!=s.end()&&s.find(x+p+q+r)!=s.end())
{
cout<<"Yes"<<endl;
return 0;
}
}
cout<<"No"<<endl;
return 0;
}
E; dp

题意:从(x,y)坐标变换,至 x+a,y+b or ,x+c,y+d or,x+e,y+f;
不能移动到故障坐标;求可以总共走的路径在n次内移动;
无终点限制、仅要求步数;不能踩的点;
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5,mod=998244353;
int n,m;
ll a,b,c,d,e,f,sum=0;
typedef pair<ll,ll>PII;
PII q[N];//存故障坐标
#define x first
#define y second
ll dp[303][303][303];//存每一次移动步数
bool cmp(PII t1,PII t2)
{
if(t1.x==t2.x)
return t1.y<t2.y;
return t1.x<t2.x;
}
int main()
{
cin>>n>>m;
cin>>a>>b>>c>>d>>e>>f;
for(int i=0;i<m;i++)
cin>>q[i].x>>q[i].y;
sort(q,q+m,cmp);
dp[0][0][0]=1;
for(int i=0;i<=n;i++)//一共进行n次,某一次变化可选可不选,所以有0;
{
for(int j=0;j<=n-i;j++)
{
for(int k=0;k<=n-i-j;k++)//x坐标增加的是a、c、e的倍数;
{
ll xx=i*a+j*c+k*e;
ll yy=i*b+j*d+k*f;
ll l=0,r=m-1,ans=0;
while(l<=r)//二分从故障坐标种找是否有重合和已选坐标;
{
ll mid=l+r>>1;
if(q[mid].x<xx||(q[mid].x==xx&&q[mid].y<yy))
l=mid+1;
else
r=mid-1;
}
if(q[l].x==xx&&q[l].y==yy&&l!=m)continue;//l不能越边界;
//符合条件的则进行方案数增加;每一次都可从前一个来;
if(i)dp[i][j][k]+=dp[i-1][j][k];
if(j)dp[i][j][k]+=dp[i][j-1][k];
if(k)dp[i][j][k]+=dp[i][j][k-1];
dp[i][j][k]%=mod;
}
}
}
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n-i;j++)
{
int k=n-i-j;
sum=(sum+dp[i][j][k])%mod;
}
}//最后计算的是每一步的总和;
cout<<sum;
return 0;
}
F:F - Manhattan Cafe
题意:给定p、q找到符合条件的r的个数;条件:在p[i]的前i个曼哈顿和(p到r)<=D,且q[i]的前i个曼哈顿和(p到r)<=D;
解题:
曼哈顿距离+dp
本文探讨了两个编程问题:一是通过二分查找和dp实现坐标变换路径计数,避免故障区域;二是利用曼哈顿距离和动态规划解决前缀和问题,寻找符合条件的r值。通过这两个算法,解决在给定约束下路径选择和和值计算问题。

840

被折叠的 条评论
为什么被折叠?



