P8452 「SWTR-8」15B03题解

Solution

第一问

很显然,贪心,每两行选其中一行,每两个数选其中一个,就是 \(n\cdot m-((n+1)/2)*((m+1)/2)\)

第二问

还是贪心,留下的每个点尽量远离他的最远点对。

显然,对于 \((x,y)\) 的最远点对一定是 \((1,1),(1,m),(n,1),(n,m)\) 中的一个。

所以首先考虑将这四个角保留。

剩下点对的又分为 \(4\) 种。

  • \((x,y)\{x \in [1,(n+1)/2],y \in [1,(m+1)/2] \}\) 这一类的最远点对是 \((n,m)\)

  • \((x,y)\{x \in [(n+1)/2,n],y \in [1,(m+1]/2] \}\) 这一类的最远点对是 \((1,m)\)

  • \((x,y)\{x \in [1,(n+1)/2],y \in [(m+1]/2,m] \}\) 这一类的最远点对是 \((n,1)\)

  • \((x,y)\{x \in [(n+1)/2,n],y \in [(m+1]/2,m] \}\) 这一类的最远点对是 \((n,m)\)

所以分别按照这四种情况进行构造。

特殊情况

  • \(n \leq 2,m \leq 2\) 这种情况是没法保留的。所以答案为 \(0\)

  • \(n=2\) 时,按照原来的思路就只能构造一行,是不符合最优。所以对于 \(y \leq (m+1)/2\) 保留在第一行,剩下的保留在第二行。

//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("inline")
#include<bits/stdc++.h>
#define re register
#define fep(i,l,r) for(re int i=l;i<=r;++i)
#define For(i,u) for(re int i=head[u];i;i=e[i].nxt)
#define feb(i,r,l) for(re int i=r;i>=l;--i)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define LL long long
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
//#define int long long
#define pr pair<int,int>
#define mpr make_pair
using namespace std;

const int N = 2000+5,M = 10,mod = 1e9+7;
int n,m; bool vis[N][N];

inline int read() { int s=0,w=1; char ch=getchar(); while(!(ch<='9'&&ch>='0')) {if(ch=='-') w=-1; ch=getchar();} while(ch<='9'&&ch>='0') {s=(s<<1)+(s<<3)+ch-'0'; ch=getchar();} return s*w; }
inline void write(int x) { if(x>=10) write(x/10); putchar(x%10+'0'); }
inline void print(int x,char ch) { if(x<0) putchar('-'),x=~(x-1); write(x); putchar(ch);}
inline double get(int x1,int y1,int x2,int y2) {return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}

inline void init(int x)
{
	int now=1;
	while(now<=(m+1)/2) vis[x][now]=true,now+=2;
	feb(i,m,now) vis[x][i--]=true;
}

inline double solve()
{
	double ans=0; if(n<=2&&m<=2) return 0;
	fep(i,1,n) fep(j,1,m) vis[i][j]=false;
	if(n!=2)
	{
		int now=1;
		while(now<=(n+1)/2) init(now),now+=2;
		feb(i,n,now) init(i--);
	}
	else
	{
		int now=1;
		while(now<=(m+1)/2) vis[1][now]=true,now+=2;
		feb(i,m,now) vis[2][i--]=true;
	}
	fep(i,1,n)
	{
		fep(j,1,m) if(vis[i][j])
		{
		//	cout<<i<<" "<<j<<endl;
			if(n!=2) ans+=max(max(get(i,j,1,1),get(i,j,1,m)),max(get(i,j,n,1),get(i,j,n,m)));
			else ans+=max(get(i,j,1,1),get(i,j,2,m));
		}
	}
	return ans;
}

signed main()
{
	int type=read(),_T=read();
	while(_T--)
	{
		n=read(),m=read();
		print(n*m-((n+1)/2)*((m+1)/2),' ');
		printf("%.20lf\n",solve());
	}
	return 0;
}
posted @ 2022-07-30 17:02  starrylasky  阅读(32)  评论(0)    收藏  举报