这个题其实就是个DP,只不过需要优化一下,用到类似单调队列~
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf=1<<29;
const int maxn=1100;
const int maxm=60;
int n,m;
int x,dp[maxm][maxn];
struct Node
{
int sa;
int sb;
bool operator < (const Node &a)const{
return sa<a.sa;
}
}a[maxm][maxn];
void Init()
{
for(int i=0;i<=m;i++)
for(int j=0;j<=n;j++)
dp[i][j]=inf;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&m,&n,&x);
Init();
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
scanf("%d",&a[i][j].sa);
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
scanf("%d",&a[i][j].sb);
for(int i=0;i<m;i++)
sort(a[i],a[i]+n);
for(int i=0;i<n;i++)
dp[0][i]=abs(a[0][i].sa-x)+a[0][i].sb;
for(int i=1;i<m;i++)
{
int index=0;
int mini=inf;
for(int j=0;j<n;j++)
{
while(index<n&&a[i-1][index].sa<=a[i][j].sa)
{
mini=min(mini,dp[i-1][index]-a[i-1][index].sa);
index++;
}
dp[i][j]=min(dp[i][j],mini+a[i][j].sa+a[i][j].sb);
}
index=n-1,mini=inf;
for(int j=n-1;j>=0;j--)
{
while(index>=0&&a[i-1][index].sa>a[i][j].sa)
{
mini=min(mini,dp[i-1][index]+a[i-1][index].sa);
index--;
}
dp[i][j]=min(dp[i][j],mini-a[i][j].sa+a[i][j].sb);
}
}
int ans=inf;
for(int i=0;i<n;i++)
ans=min(ans,dp[m-1][i]);
printf("%d\n",ans);
}
return 0;
}