CF424D Biathlon Track 题解

题意

分析

真·暴力踩标算

记录从上至下、从下至上、从左至右、从右至左花费时间的前缀和,暴力枚举每一个左上角的点和右下角的点的坐标,计算出此时的总时间和 \(t\) 的差,如果比目前的最小值小就更新答案。时间复杂度大概为 \(O(\frac{n^2m^2}{4})\) ,显然会 TLE ,但是时限 4.5s ,随便卡卡就过了。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=307;
inline void qread(){}template<class T1,class ...T2>
inline void qread(T1 &a,T2&... b)
{
	register T1 x=0;register bool f=false;char ch=getchar();
	while(ch<'0') f|=(ch=='-'),ch=getchar();
	while(ch>='0') x=(x*10)+(ch^48),ch=getchar();
	x=(f?-x:x);a=x;qread(b...);
}
template<class T>inline T qmax(const T &a,const T &b){return a>b?a:b;}
template<class T>inline T qmin(const T &a,const T &b){return a<b?a:b;}
int n,m,t,tp,tu,td,a[MAXN][MAXN],pre[4][MAXN][MAXN];
int f(int a1,int b1,int a2,int b2)
{
	if(!a2||a2==n+1||!b2||b2==m+1) return 0;
	if(a[a1][b1]==a[a2][b2]) return tp;
	if(a[a1][b1]<a[a2][b2]) return td;
	return tu;
}
void init()
{
	int i,j;
	for(i=1;i<=n;i++) for(j=1;j<=m;j++) pre[0][i][j]=pre[0][i][j-1]+f(i,j,i,j-1); // 从左往右
	for(i=1;i<=n;i++) for(j=m;j>=1;j--) pre[1][i][j]=pre[1][i][j+1]+f(i,j,i,j+1); // 从右往左
	for(j=1;j<=m;j++) for(i=1;i<=n;i++) pre[2][i][j]=pre[2][i-1][j]+f(i,j,i-1,j); // 从上往下
	for(j=1;j<=m;j++) for(i=n;i>=1;i--) pre[3][i][j]=pre[3][i+1][j]+f(i,j,i+1,j); // 从下往上
}
int mn=1e9+7,a1,b1,a2,b2;
signed main()
{
	qread(n,m,t,tp,tu,td);int i,j,k,l;
	for(i=1;i<=n;i++) for(j=1;j<=m;j++) qread(a[i][j]);init();
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=m;j++)
		{
			for(k=i+2;k<=n;k++)
			{
				for(l=j+2;l<=m;l++)
				{
					int tmp=pre[0][i][l]-pre[0][i][j]+ // 上面的一行
					        pre[1][k][j]-pre[1][k][l]+ // 下面的一行
							pre[2][k][l]-pre[2][i][l]+ // 右面的一列
							pre[3][i][j]-pre[3][k][j]; // 左面的一列
					tmp=abs(t-tmp);
					if(mn>=tmp)
					{
						mn=tmp;
						a1=i,b1=j,a2=k,b2=l;
					}
				}
			}
		}
	}
	printf("%lld %lld %lld %lld\n",a1,b1,a2,b2);
	return 0;
}
posted @ 2022-02-17 19:49  l_x_y  阅读(30)  评论(0编辑  收藏  举报