【题解】 模拟赛2 题解

T1

假设商品价格为x
618:int(x*0.66)
211:x-(x/100)*35
两者比较一下大小即可

#include
using namespace std;

int x,x1,x2;

int main(){
	scanf("%d",&x);
	x1 = x*0.66;
	x2 = x-(x/100)*35;
	if (x1 == x2) printf("both\n%d",x1);
	if (x1 > x2) printf("211\n%d",x2);
	if (x1 < x2) printf("618\n%d",x1);
	return 0;
}

T2

假设一个数x
令S= x 2 x^2 x2
如何从S的末尾中取出和x相同位数的数呢?
我们需要知道x的位数为m
那么令S% 1 0 m 10^m 10m就能得到末尾的数

如果相同,那么就是自守数,累加后输出即可

#include
using namespace std;

int a,b,cnt;
int f[101000];

bool Check(int x){
	int X = x*x,XX = x;
	int xx = 1;
	while (x) xx*=10,x/=10;
	if (X%xx == XX) return 1;
	return 0;
}

void Work(int x){
	if (Check(x)) f[++cnt] = x;
	return;
}

int main(){
	scanf("%d %d",&a,&b);
	for (int i = a; i <= b; i++) Work(i);
	printf("%d\n",cnt);
	for (int i = 1; i <= cnt; i++) printf("%d\n",f[i]);
}

T3

首先看题目:
这个油管是东西向
所以我们只需要考虑油田的纵坐标而不需要管横坐标
那么如何放置主管道才能使距离和最小呢?
我们假设先把油管放到最下面的油井中
此时得到一个距离 S S S
那么,我们将管道往上移一格
此时距离会变成多少呢?
不难想出
此时,第一个油井到他的距离会多1,而第2~n个油井的距离到他的距离就会少1
减少的距离大于增加的距离,就意味着我们仍然可以往上移

于是我们一直移……
移到什么时候,减少的会和增加的相等,或者减少的会小于增加的呢?
不难想到,就是中间的时候,减少的会等于增加的,再上去,减少的就会小于增加的,距离就会变长了

所以,距离最小的时候,就是把主管道放在中位数位置的时候。

那么知道主管道的位置了,距离和算一下也就简单了

#include
using namespace std;

const int N = 1e5+100;
int n;
int a[N],ans = 0;


int main(){
	freopen("1.in","r",stdin);
	freopen("1.out","w",stdout);
	scanf("%d",&n);
	for (int i = 1; i <= n; i++) scanf("%d %d",&a[i],&a[i]);
	sort(a+1,a+n+1);
	int d = a[(1+n)/2];
	for (int i = 1; i <= n; i++) ans+=abs(d-a[i]);
	printf("%d",ans);
}

T4

这道题是一个搜索
假设我们先不管船只放置不合理的情况
我们先把所有的船只数量算出来

设一个数组 f [ i ] [ j ] f[i][j] f[i][j]来记录位置 ( i , j ) (i,j) (i,j)是否被搜索过
遍历一遍海域,如果当前位置是 # \# #并且还没有被搜索过,说明当前位置出现了一艘新船,我们就开始搜索
怎么搜素呢?
从当前位置开始上下左右开始扩散,如果扩散到的地方未搜索过且是’#',就扩散过去,直到当前船搜索完,把扩散过的地方打标记表示扩散过即可。
这样做一遍我们就能知道船只的数量

但是当前船只的形状不一定是矩形。
如何判断当前船只的形状是否是矩形呢?

我们考虑矩形的特性:
有一个左上角端点(x,y),一个右下角端点(xx,yy)
也就是说我们只需要知道一个矩形的左上角和右下角我们就能确定一个矩形。

左上角坐标即最小横坐标,最小纵坐标
右下角坐标即最大横坐标,最大纵坐标

对于每条船,我们记录他的左上角端点,右下角端点
这样就确定了一个矩形范围
什么时候这艘船是合法的呢?
在这个范围内全是 # \# #,这就说明这个矩形范围内全是船只,放置合理。
同理,只要出现一个 ′ . ′ '.' .,那么当前这个船只的形状就不是一个合法的矩形
即放置不合理

这样就做出了判断

#include
using namespace std;

const int N = 2e3+10;
const int dx[4] = {0,0,1,-1};
const int dy[4] = {1,-1,0,0};

int n,m,cnt;
int Minx[N*N],Miny[N*N],Maxx[N*N],Maxy[N*N];
int a[N][N],f[N][N];

void Dfs(int x,int y){
	if (x<1 || y<1 || x>n || y>m) return;
	if (a[x][y] == 0) return;
	if (f[x][y]) return;
	f[x][y] = 1;
	Minx[cnt] = min(Minx[cnt],x);
	Miny[cnt] = min(Miny[cnt],y);
	Maxx[cnt] = max(Maxx[cnt],x);
	Maxy[cnt] = max(Maxy[cnt],y);//记录左上角端点,右下角端点
	for (int i = 0; i < 4; i++) Dfs(x+dx[i],y+dy[i]);
}

bool Check(int x){
	for (int i = Minx[x]; i <= Maxx[x]; i++)
	  for (int j = Miny[x]; j <= Maxy[x]; j++)
	    if (a[i][j] == 0) return 0;
	return 1;
}

int main(){
	scanf("%d %d",&n,&m);
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= m; j++){
	  	  char ch = getchar();
	  	  while (ch!='.' && ch!='#') ch = getchar();
	  	  a[i][j] = (ch == '#');
	  }
	for (int i = 1; i <= n*m; i++) Minx[i] = n*m+1,Miny[i] = n*m+1;//初始化
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= m; j++)
	  if (!f[i][j] && a[i][j]) ++cnt,Dfs(i,j);//出现新船只
	bool F = 1;
	for (int i = 1; i <= cnt; i++)
	  if (!Check(i)) {F = 0; break;}//判断是否出现不合理的船只
	if (F) printf("There are %d ships.",cnt);
	else printf("Bad placement.");
	return 0;
}

另一种判断方法

其实并不是只有上述一种判断方法。
我们考虑什么时候一条船的放置方式会不合法
肯定是在某个地方出现了空隙
肯定是在某个地方出现了如下的情况:
【题解】 模拟赛2 题解_第1张图片

假设 a [ i ] [ j ] = 1 a[i][j]=1 a[i][j]=1表示当前位置是#,否则就是’.’
出现上述情况意思就是:
a [ i ] [ j ] + a [ i + 1 ] [ j ] + a [ i ] [ j + 1 ] + a [ i + 1 ] [ j + 1 ] = = 3 a[i][j]+a[i+1][j]+a[i][j+1]+a[i+1][j+1] == 3 a[i][j]+a[i+1][j]+a[i][j+1]+a[i+1][j+1]==3
说明中间出现了空隙,肯定无法构成一个完整的矩形

遍历一遍整个图看一下是否存在这样的情况即可

你可能感兴趣的:(题解,滨小之旅)