题目大意
有一个 n行m列的矩阵,每个格子有一花费Tij,要求在每行选出恰好一个格子,使得这n个格子的Tij 之和最小,每个格子还有一权值Wij.对于相邻两行选择的格子(i,j1)(i-1,j2)要求abs(j1-j2)<=W(i,j1)+W(i-1,j2),多组数据T(2.5S)
Sample Input
1
3 5
9 5 3 8 7
8 2 6 8 9
1 9 7 8 6
0 1 0 1 2
1 0 2 1 1
0 2 1 0 2
Sample Output
10
数据范围与约定
对于 20% 的数据,保证数据,保证 T = 1
对于另 30% 的数据,保证 m < = 500 ;
对于 100% 的数据,保证 T<= 5, 2≤n≤100 ,1 <=m<=5000,0<= Tij 、Wij≤100000
这个的dp方程恨好推啦,那么前50分就可以这样拿
#include<bits/stdc++.h> #define INF 2100000001 #define N 103 #define M 5003 #define re register using namespace std; int read() { int x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } int c[N][M],w[N][M],dp[N][M]; int main() { // freopen("elect.in","r",stdin); // freopen("elect.out","w",stdout); int T=read(); int n=read(),m=read(); while(T--) { for(re int i=1;i<=n;++i) for(re int j=1;j<=m;++j) c[i][j]=read(); for(re int i=1;i<=n;++i) for(re int j=1;j<=m;++j) w[i][j]=read(); for(re int i=2;i<=n;++i) for(re int j=1;j<=m;++j) dp[i][j]=INF; for(re int i=1;i<=m;++i) dp[1][i]=c[1][i]; for(re int i=2;i<=n;++i) { for(re int j=1;j<=m;++j)//now { for(re int k=1;k<=m;++k)//last { if(w[i][j]+w[i-1][k]>=abs(j-k)) dp[i][j]=min(dp[i][j],dp[i-1][k]+c[i][j]); } } } int ans=INF; for(re int i=1;i<=m;++i) ans=min(ans,dp[n][i]); printf("%d\n",ans); } } /* 1 3 5 9 5 3 8 7 8 2 6 8 9 1 9 7 8 6 0 1 0 1 2 1 0 2 1 1 0 2 1 0 2 */