题意:给出一个布满数字的网格,可以上下左右走,若下一个格子的数字比当前格子要大或者小或者一样,分别都要付出代价。给出一个期望代价,问当要求顺时针走出一个长宽均大于3的矩形的四条边后,最接近期望代价的情况。
做法:由于长宽大于3,直接暴力枚举即可。
#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
using namespace std;
int val[3];
int psum[4][310][310],a[310][310];
int main()
{
int n,m,t;
scanf("%d%d%d",&n,&m,&t);
for(int i=0;i<3;i++)
scanf("%d",&val[i]);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&a[i][j]);
for(int i=0;i<n;i++)
for(int j=1;j<m;j++)
if(a[i][j-1]==a[i][j])
psum[0][i][j]=psum[0][i][j-1]+val[0];
else if(a[i][j-1]<a[i][j])
psum[0][i][j]=psum[0][i][j-1]+val[1];
else
psum[0][i][j]=psum[0][i][j-1]+val[2];
for(int i=0;i<n;i++)
for(int j=m-2;j>-1;j--)
if(a[i][j]==a[i][j+1])
psum[1][i][j]=psum[1][i][j+1]+val[0];
else if(a[i][j]>a[i][j+1])
psum[1][i][j]=psum[1][i][j+1]+val[1];
else
psum[1][i][j]=psum[1][i][j+1]+val[2];
for(int i=0;i<m;i++)
for(int j=1;j<n;j++)
if(a[j-1][i]==a[j][i])
psum[2][j][i]=psum[2][j-1][i]+val[0];
else if(a[j-1][i]<a[j][i])
psum[2][j][i]=psum[2][j-1][i]+val[1];
else
psum[2][j][i]=psum[2][j-1][i]+val[2];
for(int i=0;i<m;i++)
for(int j=n-2;j>-1;j--)
if(a[j][i]==a[j+1][i])
psum[3][j][i]=psum[3][j+1][i]+val[0];
else if(a[j][i]>a[j+1][i])
psum[3][j][i]=psum[3][j+1][i]+val[1];
else
psum[3][j][i]=psum[3][j+1][i]+val[2];
int mn=INT_MAX,ans[4];
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
for(int k=i+2;k<n;k++)
{
int t1=psum[3][i][j]-psum[3][k][j];
for(int l=j+2;l<m;l++)
{
int t2=psum[2][k][l]-psum[2][i][l];
int t3=psum[0][i][l]-psum[0][i][j];
int t4=psum[1][k][j]-psum[1][k][l];
int sub=abs(t-t1-t2-t3-t4);
if(sub<mn)
{
mn=sub;
ans[0]=i;ans[1]=j;ans[2]=k;ans[3]=l;
}
}
}
for(int i=0;i<4;i++)
printf("%d ",ans[i]+1);
}