题目描述
有一个n×m的网格地图,每个点有个值aijaij,现在牛牛要从(1,1)走到(n,m)(1,1)走到(n,m),他可以往右边或者往下走,每次到一个点会获得当前的点权值,并将权值和mod 1e4+71e4+7,当牛牛从不同方式走到(n,m)(n,m)的时候能获得多少种权值和?
输入描述:
第一行输入正整数n,m(n,m≤100)n,m(n,m≤100)
接下来 nn 行每行有 mm 个正整数,分别代表aijaij(aij≤109)(aij≤109)
输出描述:
输出一行,表示到(n,m)点的时候的权值和种数
示例1
输入
2 2 1 1 2 2
输出
2
说明
有1+1+2和1+2+2两种
思想就是跑dp:
到达一个点只能是有上或者左转移而得到 那么状态转移方程容易得到:
主要找从1,1到最后n,m 点 有多少不同的权值可以达到,我们直接三维数组进行存储,st[i][j][k] st[i][j] 代表位置,[k] 代表当前的权值,这里只要判断当前的st是否为1即可,最后累加
注意不要开ll 看题目数据
const int N = 100010, M = 200010;
const int mod = 1e4 + 7;
bool st[110][110][10010];
int a[110][110];
int main(){
int n, m;
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; i ++){
for (int j = 1; j <= m; j++){
scanf("%d",&a[i][j]);
a[i][j] %=mod;
}
}
st[1][1][a[1][1]] = 1;
for (int i = 1; i <= n; i ++){
for (int j = 1; j <= m; j ++){
if (i == 1 && j == 1) continue;
for (int k = 0; k < mod ;k ++){
st[i][j][(a[i][j] + k)%mod] |= st[i-1][j][k];
st[i][j][(a[i][j] + k)%mod] |= st[i][j - 1][k];
}
}
}
int res = 0;
for (int i = 0; i < mod; i ++){
if (st[n][m][i]) res ++;
}
printf("%d\n",res);
return 0;
}