22.3.23

1,K倍区间2,bfs保存最短路径


1,K倍区间

讲一讲做题流程:

首先先去想暴力该怎么做

3层for循环,第一层控制r,第二层控制l,第三层求r到l的和,然后看sum%k==0 ,相等ans++,不等无操作,所以基本上复杂度是O(n^3);那数据范围是1e5,所以3次方就是1e15,肯定过不了,那就去想优化;

知道暴力怎么做后,再去想可以优化的地方

首先容易想到的就是第三层循环求和,我们可以预处理前缀和,用前缀和去做,这样求和的操作就是O(1),所以时间复杂度降为O(n^2),1e10,能过掉一般的数据了应该;但是一个简单的前缀和优化这还不够,深一点的优化总要和题目性质挂个勾

 

#include<bits/stdc++.h>
#define rep1(i,a,n) for(int i=a;i<n;i++) 
#define rep2(i,a,n) for(int i=a;i<=n;i++) 
#define per1(i,n,a) for(int i=n;i>a;i--) 
#define per2(i,n,a) for(int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
int n,k;
const int N=1e5+10;
ll s[N];
int cnt[N];
int main()
{
	quick_cin();
	cin>>n>>k;
	rep2(i,1,n)
	{
		int x;cin>>x;
		s[i]=s[i-1]+x;
	}
	ll ans=0;
	cnt[0]=1;
	rep2(i,1,n)
	{
		ans+=cnt[s[i]%k];
		cnt[s[i]%k]++;
	}
	cout<<ans;
	return 0;
}

2,bfs储存最短路径

题意:如果有最短路径,打印最短路径,如果到不了终点,输出NO,

不同于一般的求最短路长度,这次我们还需要把路径表示出来,how?

如果我们想在bfs遍历过程中想方法去存储,我感觉难办,因为无法确定每次到的要存储哪一个点,都存储了,哪个点是最短路上的点呢?

这时候就需要一个确定状态的点,是哪个点呢?

就是每次用该点去遍历其他地方的点,也就是每次取得队头的点,我们用它来取四个方向找点,所以4个方向的点都和它有关,我们就去存储这个点,这样就可以得到一种”父子“关系;每次得到的新点都指向它的父节点,类似于树;这样一般bfs()完后,就得到了一个指向关系;因为要找的是最短路,我们可以确定了终点,只要从终点回溯,一直往前找父节点,这样就能找到起点;海能确保是最短路,因为就是从终点出发的;

所以正着一遍bfs,然后再回溯一遍树,即可得到最短路径;

回溯:注意细节;

void getpath()
{
	int i=n-2,j=n-2;
	stack<PII>ans;
	while(hs[i][j].first!=0&&hs[i][j].second!=0)
	{
		ans.push({i,j});
		int x=hs[i][j].first;//一定先用x,y存储,直接i=hs[i][j].first,
                                //会影响j=hs[i][j].second,因为i改变了;
		int y=hs[i][j].second;
		i=x;
		j=y;
	}
	ans.push({1,1});//(1,1)不会被存进去,手动push
	while(ans.size())
	{	
		auto t=ans.top();
		ans.pop();
		printf("(%d,%d)",t.first,t.second);
	}
}

代码; 

#include<bits/stdc++.h>
#define rep1(i,a,n) for(int i=a;i<n;i++) 
#define rep2(i,a,n) for(int i=a;i<=n;i++) 
#define per1(i,n,a) for(int i=n;i>a;i--) 
#define per2(i,n,a) for(int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
int n;
int maze[1010][1001];
int f[101][101];
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
PII hs[101][101];
bool flag=0;
void bfs()
{
	memset(f,-1,sizeof f);
	queue<PII>q;
	f[1][1]=0;
	q.push({1,1});
	while(q.size())
	{
		auto t=q.front();q.pop();
		if(t.first==n-2&&t.second==n-2)
		{
			flag=1;
			break;
		}
		rep2(i,0,3)
		{
			int  x=t.first+dx[i],y=t.second+dy[i];
			if(x>0&&x<n-1&&y>0&&y<n-1&&maze[x][y]==0&&f[x][y]==-1)
			{
				q.push({x,y});
				hs[x][y] ={t.first,t.second};
				f[x][y]=f[t.first][t.second]+1;
			}
		}
	}
}
void getpath()
{
	int i=n-2,j=n-2;
	stack<PII>ans;
	while(hs[i][j].first!=0&&hs[i][j].second!=0)
	{
		ans.push({i,j});
		int x=hs[i][j].first;
		int y=hs[i][j].second;
		i=x;
		j=y;
	}
	ans.push({1,1});
	while(ans.size())
	{	
		auto t=ans.top();
		ans.pop();
		printf("(%d,%d)",t.first,t.second);
	}
}
int main()
{
	quick_cin();
	cin>>n;
	rep2(i,0,n-1)
		rep2(j,0,n-1)cin>>maze[i][j];
	bfs();
	if(flag)getpath();
	else printf("NO");
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dull丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值