22/5/13

一,训练赛补题:1,Searching for Soulmates;2,Walking Home;二,cf round 789 div2补题:1, Tokitsukaze and Strange Inequality;三,acwing 提高课:acwing 188.武士风度的牛;acwing 173. 矩阵距离;


一,训练赛补题:

1,Searching for Soulmates

题意:给出两个数a,b,有如下操作:a*2,a/2,或者a+1,来使a==b,问最小的操作数;

思路:首先乘和除一定不会交替出现,因为会相互抵消掉的;所以一定有个分界点;

很容易想到分界点前后是先除后乘。

之后 如何运用乘和加来操作呢;

如下情况:

用f(x,y)表示使x和y相等的最小次数;

①:a>b 无解;

②:a*2>b,此时只能加法,return b-a;

③:b是奇数,return f(a,b-1)+1,解释:使a变成b-1,在加1次加法操作;(这个思想太6了);

④:b是偶数且a<=b/2,return f(a,b/2)+1,解释:使a变成b/2,所以前提是a<=b/2,然后进行一次乘法操作;

其实分界点在a<=b后是随机的,所以只要a<=b,对于每次的a,都设置一个分界点,去操作;

#include<bits/stdc++.h>
//#pragma GCC optimize(2)
#define rep1(i,a,n) for(ll i=a;i<n;i++) 
#define rep2(i,a,n) for(ll i=a;i<=n;i++) 
#define per1(i,n,a) for(ll i=n;i>a;i--) 
#define per2(i,n,a) for(ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pb push_back
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
ll a,b;
ll f(ll a,ll b)
{
	if(a>b)return 1e18;
	if(a*2>b)return b-a;
	if(b%2)return f(a,b-1)+1;
	if(b%2==0&&a<=b/2)return f(a,b/2)+1;
}
void solve()
{
	cin>>a>>b;
	ll c1=0;
	if(a==b)cout<<0<<endl;
	else
	{
		ll k=1e18;
		while(a>1)
		{
			if(a<=b)
			{
				ll c2=f(a,b);
				k=min(k,c1+c2);
			}
			if(a%2)a++;
			else a/=2;
			c1++;
		}
		cout<<k<<endl;
	}
}
signed main()
{
    quick_cin();
	int T;
	cin>>T;
	while(T--)solve();
    return 0;
}

2,walking home

题意:

给你一个n*n的矩阵,由'.'和'H'组成,带'H'的方格不可以走,牛在(1,1)只能向下和向右走,

且转向次数不超过k次,问到达(n,n)有几种方案;

思路:dfs+剪枝优化;

#include<bits/stdc++.h>
//#pragma GCC optimize(2)
#define rep1(i,a,n) for(ll i=a;i<n;i++) 
#define rep2(i,a,n) for(ll i=a;i<=n;i++) 
#define per1(i,n,a) for(ll i=n;i>a;i--) 
#define per2(i,n,a) for(ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pb push_back
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const int N=1e2+10;
char a[N][N];
int st[N][N][5][5];
int n,k;
int dfs(int x,int y,int cs,int dir)
{
	if(cs>k)return 0;
	if(cs==k&&x!=n&&y!=n)return 0;
	if(x>n||y>n)return 0;
	if(x==n&&y==n) return 1;
	int sum=0;
	if(a[x][y]=='H')return 0;
	if(dir)
	{
		sum+=dfs(x+1,y,cs,1);
		sum+=dfs(x,y+1,cs+1,0);
	}
	else
	{
		sum+=dfs(x+1,y,cs+1,1);
		sum+=dfs(x,y+1,cs,0);
	}
	return sum;
}
void solve()
{
	cin>>n>>k;
	rep2(i,1,n)
	 rep2(j,1,n)cin>>a[i][j];
	cout<<dfs(2,1,0,1)+dfs(1,2,0,0)<<endl;

}
signed main()
{
    quick_cin();
	int T;
	cin>>T;
	while(T--)solve();
    return 0;
}

二,cf 补题:

1,Tokitsukaze and Strange Inequality

题意:

给你一个长度为n的数组p,问有多少个本质不同的四元组(a,b,c,d)满足1\leq a<b<c<d \leq n \ and \ p_a<p_c\ and \ p_b>p_d

思路:枚举;

枚举的出发点很关键,从pc出发,每次统计出前边比pc小的pa的个数,在统计出满足pb>pd的个数;

可以用树状数组来优化求pa小于pc的个数;

固定pbpc,移动pd,更新pb>pd的个数,枚举得到的答案,所以不从不漏;

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define rep1(i,a,n) for(ll i=a;i<n;++i) 
#define rep2(i,a,n) for(ll i=a;i<=n;++i) 
#define per1(i,n,a) for(ll i=n;i>a;i--) 
#define per2(i,n,a) for(ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pb push_back
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const int N=1e4+10;
int c[N];
int n,a[N];
void add(int i,int d)
{
	for(;i<=n;i+=lowbit(i))c[i]+=d;
}
int sum(int i)
{
	int s=0;
	for(;i>=1;i-=lowbit(i))s+=c[i];
	return s;
}
void solve()
{
	cin>>n;
	memset(c,0,c);
	rep2(i,1,n)cin>>a[i];
	ll ans=0;
	rep2(i,3,n)
	{
		add(a[i-2],1);
		ll num=sum(a[i]);
		rep2(j,i+1,n)
		{
			if(a[i-1]>a[j])ans+=num;
			num+=sum(a[j]);
		}
	}
	cout<<ans<<endl;

}
signed main()
{
    quick_cin();
	int T;
	cin>>T;
	while(T--)solve();
    return 0;
}

 三,

1,武士风度的牛;

题意:

思路:标准的bfs搜索,注意细节,判断下一步的地方不一定是a[i][j]=='.'才可以走,这样会把终点

'H'扔掉不走的!!,所以是a[i][j]!='*'才可以!;

if(x>0&&x<=n&&y>0&&y<=m&&a[x][y]!='*'&&st[x][y]==0)

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define rep1(i,a,n) for(ll i=a;i<n;++i) 
#define rep2(i,a,n) for(ll i=a;i<=n;++i) 
#define per1(i,n,a) for(ll i=n;i>a;i--) 
#define per2(i,n,a) for(ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pb push_back
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const int N=1e4+10;
int n,m;
char a[500][500];
int st[500][500];
int dist[500][500];
PII d[]={{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}};
int sx,sy,edx,edy;
int bfs()
{
	queue<PII>q;
	q.push({sx,sy});
	st[sx][sy]=1;
	dist[sx][sy]=0;
	while(q.size())
	{
		auto t=q.front();q.pop();
		rep1(i,0,8)
		{
			int x=t.yi+d[i].yi,y=t.er+d[i].er;
			if(x>0&&x<=n&&y>0&&y<=m&&a[x][y]!='*'&&st[x][y]==0)
			{
				st[x][y]=1;
				q.push({x,y});
				dist[x][y]=dist[t.yi][t.er]+1;
				if(x==edx&&y==edy)return dist[x][y];
			}
		}
	}
	return dist[edx][edy];
}
signed main()
{
    quick_cin();
	cin>>m>>n;
	rep2(i,1,n)
	 rep2(j,1,m)
	 {
	 	cin>>a[i][j];
	 	if(a[i][j]=='K')sx=i,sy=j;
	 	if(a[i][j]=='H')edx=i,edy=j;
	 }
	cout<<bfs();
    return 0;
}

2,矩阵距离;

题意:

 多源bfs;

其实就是起点变成了所以1的位置;然后把这些1都预先放进队列里;这样再去求各个位置的距离,由于bfs求到的一定是最短距离,所以某个位置的0被更新到的话,一定是距离它最近的1来更新的;

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define rep1(i,a,n) for(ll i=a;i<n;++i) 
#define rep2(i,a,n) for(ll i=a;i<=n;++i) 
#define per1(i,n,a) for(ll i=n;i>a;i--) 
#define per2(i,n,a) for(ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pb push_back
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const int N=1e6+10;
PII q[N];
int n,m;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
string s[1010];
int dist[1010][1010];
void bfs()
{
	memset(dist,-1,dist);
	int hh=0,tt=-1;
	rep1(i,0,n)
	 rep1(j,0,m)
	 {
	 	if(s[i][j]=='1')
	 	{
	 		q[++tt] = {i,j};
			dist[i][j]=0; 	
		}
	 }
	while(hh<=tt)
	{
		auto t=q[hh++];
		rep1(i,0,4)
		{
			int x=t.yi+dx[i],y=t.er+dy[i];
			if(x<0||x>=n||y<0||y>=m)continue;
			if(dist[x][y]!=-1)continue;
			dist[x][y]=dist[t.yi][t.er]+1;
			q[++tt] = {x,y};
		}
	}
}
signed main()
{
    quick_cin();
	cin>>n>>m;
	rep1(i,0,n)cin>>s[i];
	bfs();
	rep1(i,0,n)
	{
		rep1(j,0,m)cout<<dist[i][j]<<" ";
		cout<<endl;
	}
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Dull丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值