【codeforces】 Codeforces Round #546 (Div. 2)

目录

A. Nastya Is Reading a Book

B. Nastya Is Playing Computer Games(找规律)

C. Nastya Is Transposing Matrices(思维)

D. Nastya Is Buying Lunch(贪心)


A. Nastya Is Reading a Book

【题意】一本书里有若干个章节,每个章节有若干页。在读的时候会在第k页做标记,下次会 从第k页开始读;问,这本书还有多少个章节未完成;

【分析】数据很小,遍历过去找就好了

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=110;
struct node{
	int st;
	int ed;
}a[maxn];

int main()
{
	int n;scanf("%d",&n);
	for(int i=0;i<n;++i)
	{
		int x,y;scanf("%d%d",&x,&y);
		a[i].st=x;a[i].ed=y;
	}
	int k;scanf("%d",&k);
	int index=-1;
	for(int i=0;i<n;++i)
	{
		if(a[i].st<=k && a[i].ed>=k)
		{
			index=i;break;
		}
	}
	printf("%d\n",n-index);
	
 } 

B. Nastya Is Playing Computer Games(找规律)

【题意】每个井盖上初始都有一块石头,当左右移动或者扔石头(可以扔到其他任意一个井盖)或者下去捡金币都需要移动1步;给出井盖数和初始位置,问最小的步数;

【分析】画几个图就发现,不管怎样,要先把石头移到相邻的井盖上;

最后的答案分为三部分:扔石头的步数+左右移动位置的步数+捡金币的步数;

捡金币的步数是固定的,即n;

左右移动的步数与初始位置有关,并且具有对称性,(如,在第一个位置和在最后一个位置答案相同),所以要处理一下初始位置;

扔石头的步数,开始的时候都要把石头扔到相邻的位置,所以步数=1+2+n-2;

【代码】

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n,k;scanf("%d%d",&n,&k);
	int f=n/2;
	if(n&1)f++;
	if(k>f)f=n-k+1;
	else f=k;
//	cout<<"k="<<k<<endl;
	printf("%d\n",3+n-2+n-2+f+n);
}

C. Nastya Is Transposing Matrices(思维)

【题意】问矩阵A能否转置(整个转置+部分转置)成矩阵B

【分析】看了题解才知道这样做的...(

矩阵的转置实际上就是关于对角线对称的来进行变换;

所以,可以把元素存起来,位置和元素;这样关于对角线对称的元素的位置是相同的;

然后再在输入矩阵B的时候进行判断,如果对称的位置没有元素(≤0)说明不可以转置成功;

【代码】

#include <bits/stdc++.h>
using namespace std;

const int maxn=510;
int a[maxn][maxn];
int b[maxn][maxn];

map<int,int>times[maxn*2];

int main()
{
	int n,m;scanf("%d%d",&n,&m);
	int f=1;
	for(int i=0;i<n;++i)
    {
    	for(int j=0;j<m;++j)
        {
        	scanf("%d",&a[i][j]);
        	times[i+j+1][a[i][j]]++;
        }
    }
    for(int i=0;i<n;++i)
    {
    	for(int j=0;j<m;++j)
    	{
    		scanf("%d",&b[i][j]);
    		if(times[i+j+1][b[i][j]]<=0)f=0;
    		times[i+j+1][b[i][j]]--; 
        }
	}
	if(f)puts("YES");
	else puts("NO");
}

D. Nastya Is Buying Lunch(贪心)

【题意】若干个人站成一队,现在要把队尾的人通过给出的可以交换的条件尽可能往前调,问最多能前进多少位置;

【分析】(→

最后一个人能前进多少位置取决于前面的人有多少能和最后一个人进行交换,并且可能的话,进行一直交换;

从倒数第二个人开始,如果这个人和原来的最后一个人可以进行交换,那么进行交换直至和最后一个人交换,再统计前进的位置即可。

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=3e5+10;
int a[maxn];
map<pair<int,int>,int>mp;

int main()
{
	int n,m;scanf("%d%d",&n,&m);
	for(int i=0;i<n;++i)scanf("%d",&a[i]);
	for(int i=0;i<m;++i)
	{
		int u,v;scanf("%d%d",&u,&v);
		mp[make_pair(u,v)]=1;
	}
	int last=n-1;
	for(int i=n-2;i>=0;--i)
	{
		if(mp[make_pair(a[i],a[last])])
		{//前面的人和最后一个人直接相连才有可能进行交换
			int j;
			for(j=i;j<last;++j)
			{
				if(mp[make_pair(a[j],a[j+1])])
					swap(a[j],a[j+1]);
				else break;
			}
			if(j==last)//第i个人和最后一个人可以交换,最后一个人的位置往前移
				--last;
		}
	}
	printf("%d\n",n-1-last);//统计交换的个数
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_38735931/article/details/88539492