2 3 1 2 3 2 2 1 2 3 2 2 1 1 2 4
4 8
/************************************************************************/
附上该题对应的中文题
给定n∗m(n+m为奇数)的矩阵,从(1,1)走到(n,m)且只能往右往下走,设经过的数为a1,a2...a2k,贡献为a1∗a2+a3∗a4+...+a2k−1∗a2k,求最小贡献。
若干组数据(大概5组)。 每组数据第一行两个数n,m(1≤n,m≤1000且n+m为奇数)。 接下来n行每行m个数ai,j(1≤ai,j≤100)描述这个矩阵。
对于每组数据,输出一行表示答案。
2 3 1 2 3 2 2 1 2 3 2 2 1 1 2 4
4 8
出题人的解题思路:
令dp[i][j]表示当前走到第i,j个位置的最小贡献,我们可以假定(i+j)为奇数,由该状态可以转移向最多4个位置,就可以了。
话说,这次的出题人是不是比较喜欢dp,连着出了两题dp题,让人有点小醉。这题很明显的dp题,然而,我逆着来就跪了好久好久,先是边界控制不好,再是条件控制不好,总之做得很糟糕,就连题目也是比赛结束之后一发A的,着实被学弟学妹们虐了一把#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-4 using namespace std; const int N = 1005; const int M = 15005; const int inf = 100000; const int mod = 2009; int s[N][N],w[N][N]; int main() { int n,m,i,j; while(~scanf("%d%d",&n,&m)) { memset(w,0,sizeof(w)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%d",&s[i][j]); for(i=n;i>0;i--) for(j=m;j>0;j--) { if(i==n&&j==m) { w[i][j]=0; continue; } if((i+j)%2==0) { if(i+1>n) { s[i][j]*=s[i][j+1]; w[i][j]=s[i][j]+w[i][j+1]; continue; } else if(j+1>m) { s[i][j]*=s[i+1][j]; w[i][j]=s[i][j]+w[i+1][j]; continue; } if(s[i][j]*s[i][j+1]+w[i][j+1]<s[i][j]*s[i+1][j]+w[i+1][j]) { s[i][j]*=s[i][j+1]; w[i][j]=s[i][j]+w[i][j+1]; } else { s[i][j]*=s[i+1][j]; w[i][j]=s[i][j]+w[i+1][j]; } } else { if(i<n&&j<m) w[i][j]=min(w[i][j+1],w[i+1][j]); else if(j+1>m) w[i][j]=w[i+1][j]; else w[i][j]=w[i][j+1]; } } printf("%d\n",w[1][1]); } return 0; }菜鸟成长记