题目大意

有一个 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

*/
50分

相关文章: