题目链接:点击查看
题目大意:给出一个 n ∗ m n*m n∗m 的矩阵,每个点都可以到达相邻的四个点,每条边都有一个边权,问对于每个点 ( i , j ) (i,j) (i,j),走 k k k 步可以回到 ( i , j ) (i,j) (i,j) 的最短路径
题目分析:首先不难看出 k k k 如果是奇数的话无解,然后可以将题目转换为:从 ( i , j ) (i,j) (i,j) 走 k 2 \frac{k}{2} 2k 步可以到达的最短路径,不难看出用后 k 2 \frac{k}{2} 2k 步沿着前面的路径原路返回这样一定是最优的
第一反应是暴力每个点,就是对于每个点 ( x , y ) (x,y) (x,y) 来说单独思考, d p i , j , k dp_{i,j,k} dpi,j,k 代表从点 ( x , y ) (x,y) (x,y) 出发走了 k k k 步到达点 ( i , j ) (i,j) (i,j) 的最短路径,这样思考正确性毋庸置疑,就是时间复杂度有点大: O ( n ∗ m ∗ k 2 ∗ k 2 ∗ k 2 ∗ 4 ) O(n*m*\frac{k}{2}*\frac{k}{2}*\frac{k}{2}*4) O(n∗m∗2k∗2k∗2k∗4),三个 k 2 \frac{k}{2} 2k 分别代表需要转移的矩形的长和宽,以及需要迭代的次数, 4 4 4 代表的是每次需要向四个方向转移
后来发现,我们并不需要关注起点在哪,只需要关注走了 k 2 \frac{k}{2} 2k 步之后到达 ( x , y ) (x,y) (x,y) 的最小路径是多少就行,直接乘以 2 2 2 就是我们需要的答案了
所以直接迭代 k 2 \frac{k}{2} 2k 次,更新每个点的状态即可,时间复杂度 O ( n ∗ m ∗ k 2 ) O(n*m*\frac{k}{2}) O(n∗m∗2k)
最后提一句,第一种方法卡卡常是可以过的,因为看到了前排大佬和我思路一样,但我却给写T了,代码放在后面,主要是展示思路
代码:
AC代码
// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
T f=1;x=0;
char ch=getchar();
while(0==isdigit(ch)){
if(ch=='-')f=-1;ch=getchar();}
while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=f;
}
template<typename T>
inline void write(T x)
{
if(x<0){
x=~(x-1);putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=510;
const int b[4][2]={
0,1,0,-1,1,0,-1,0};
int n,m,k;
int raw[N][N],col[N][N];//raw[i][j]:(i,j)->(i,j+1) col[i][j]:(i,j)->(i+1,j)
int dp[N][N][11];
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
read(n),read(m),read(k);
for(int i=1;i<=n;i++) {
for(int j=1;j<m;j++) {
read(raw[i][j]);
}
}
for(int i=1;i<n;i++) {
for(int j=1;j<=m;j++) {
read(col[i][j]);
}
}
if(k&1) {
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
printf("-1 ");
}
puts("");
}
return 0;
}
k/=2;
for(int t=1;t<=k;t++) {
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
dp[i][j][t]=inf;
for(int p=0;p<4;p++) {
int xx=i+b[p][0];
int yy=j+b[p][1];
if(xx<=0||xx>n||yy<=0||yy>m) {
continue;
}
int w;
if(p==0) {
w=raw[i][j];
} else if(p==1) {
w=raw[xx][yy];
} else if(p==2) {
w=col[i][j];
} else if(p==3) {
w=col[xx][yy];
}
dp[i][j][t]=min(dp[i][j][t],dp[xx][yy][t-1]+w*2);
}
}
}
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
printf("%d ",dp[i][j][k]);
}
puts("");
}
return 0;
}
TLE代码:
// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
T f=1;x=0;
char ch=getchar();
while(0==isdigit(ch)){
if(ch=='-')f=-1;ch=getchar();}
while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=f;
}
template<typename T>
inline void write(T x)
{
if(x<0){
x=~(x-1);putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=510;
const int b[4][2]={
0,1,0,-1,1,0,-1,0};
int n,m,k;
int raw[N][N],col[N][N];//raw[i][j]:(i,j)->(i,j+1) col[i][j]:(i,j)->(i+1,j)
int dp[N][N][11];
struct Node {
int x,y,step;
};
int solve(int x,int y,int k) {
for(int t=0;t<=k;t++) {
for(int i=max(x-t,1);i<=min(x+t,n);i++) {
int d=t-abs(i-x);
for(int j=max(y-d,1);j<=min(y+d,m);j++) {
dp[i][j][t]=inf;
}
}
}
dp[x][y][0]=0;
for(int t=1;t<=k;t++) {
for(int i=max(x-t,1);i<=min(x+t,n);i++) {
int d=t-abs(i-x);
for(int j=max(y-d,1);j<=min(y+d,m);j++) {
for(int p=0;p<4;p++) {
int xx=i+b[p][0];
int yy=j+b[p][1];
if(xx<=0||xx>n||yy<=0||yy>m) {
continue;
}
if(abs(xx-x)+abs(yy-y)>t-1) {
continue;
}
int w;
if(p==0) {
w=raw[i][j];
} else if(p==1) {
w=raw[xx][yy];
} else if(p==2) {
w=col[i][j];
} else if(p==3) {
w=col[xx][yy];
}
dp[i][j][t]=min(dp[i][j][t],dp[xx][yy][t-1]+w);
}
}
}
}
int ans=inf;
for(int i=max(x-k,1);i<=min(x+k,n);i++) {
int d=k-abs(i-x);
for(int j=max(y-d,1);j<=min(y+d,m);j++) {
ans=min(ans,dp[i][j][k]);
}
}
return ans*2;
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
read(n),read(m),read(k);
for(int i=1;i<=n;i++) {
for(int j=1;j<m;j++) {
read(raw[i][j]);
}
}
for(int i=1;i<n;i++) {
for(int j=1;j<=m;j++) {
read(col[i][j]);
}
}
if(k&1) {
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
printf("-1 ");
}
puts("");
}
return 0;
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
printf("%d ",solve(i,j,k/2));
}
puts("");
}
return 0;
}