Luogu P1373 小a和uim之大逃离

来源:互联网 发布:聚焦网络爬虫 软件 编辑:程序博客网 时间:2024/06/05 17:44

题目描述传送门
一看这题首先想到设d(i,j,k1,k2,0)表示在小a刚吸完i,j这个位置的魔液,小a和uim的魔瓶的魔液量分别为k1,k2时的方案数,d(i,j,k1,k2,1)表示在uim刚吸完……的方案数。
但是这样明显会爆内存…于是我就一直卡着了。后来看到讨论区有差这个字,才想到把状态减少到d(i,j,k,0)d(i,j,k,1)其中k为 小a的魔瓶量与uim的魔瓶量之差.
另外我用的是顺推,感觉更好想。
代码

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cstdlib>using namespace std;const int mo=1e9+7;int n,m,k,d[800][800][16][2],a[800][800];int main(){    scanf("%d%d%d",&n,&m,&k);    memset(d,0,sizeof(d));    for(int i=0;i<n;i++)        for(int j=0;j<m;j++){            scanf("%d",&a[i][j]);            d[i][j][a[i][j]][0]=1;        }    for(int i=0;i<n;i++)        for(int j=0;j<m;j++)            for(int u=0;u<=k;u++){                 int k1;                 if(i+1<n){                     k1=u+a[i+1][j];                     if(k1>k) k1-=(k+1);                     d[i+1][j][k1][0]=(d[i+1][j][k1][0]+d[i][j][u][1])%mo;                     k1=u-a[i+1][j];                     if(k1<0) k1+=(k+1);                     d[i+1][j][k1][1]=(d[i+1][j][k1][1]+d[i][j][u][0])%mo;                 }                 if(j+1<m){                     k1=u+a[i][j+1];                     if(k1>k) k1-=(k+1);                     d[i][j+1][k1][0]=(d[i][j+1][k1][0]+d[i][j][u][1])%mo;                     k1=u-a[i][j+1];                     if(k1<0) k1+=(k+1);                     d[i][j+1][k1][1]=(d[i][j+1][k1][1]+d[i][j][u][0])%mo;                }            }    int ans=0;    for(int i=0;i<n;i++)        for(int j=0;j<m;j++)            ans=(ans+d[i][j][0][1])%mo;    cout<<ans<<endl;    return 0;}
原创粉丝点击