【DP专题】——洛谷P1373小a和uimの大逃离

第一眼:感觉能切。

GO:传送门


看一眼数据,觉得是O(nmk)的。

尝试设f[i][j][k][l]表示在(i,j)时,此时分别有k和l的药的总方案数。

这里把两个人的行走直接算作一步。

f[i][j][k][l]=f[i-2][j][k-a[i-1][j]][l-a[i][j]]+...分别表示通过右右,右下,下右,下下达到该点的方案数。

预处理一下,以某一个点为起点,那么f[i][j][0][0]=1.

时间复杂度O(nmkk)太大,发现没必要把两个人行走算作一步(我好蠢)

直接一点,

f[i][j][k][0/1]表示(i,j)位置,此时两人液体差为k,0表示a走,1表示uim先走。

转移没啥好难想的。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int read(){
 4     int x=0,f=1;
 5     char c=getchar();
 6     while(!isdigit(c)){
 7         if(c=='-') f=-1;
 8         c=getchar();
 9     }
10     while(isdigit(c)){
11         x=x*10+c-'0';
12         c=getchar();
13     }
14     return x*f;
15 }
16 typedef long long ll;
17 const int N=810;
18 const int p=1e9+7;
19 int n,m,k,mod;
20 int a[N][N];
21 int f[N][N][16][2];
22 int main(){
23     n=read();m=read();k=read();
24     mod=k+1;
25     for(int i=1;i<=n;i++){
26         for(int j=1;j<=m;j++){
27             f[i][j][a[i][j]=read()][0]=1;
28         }
29     }
30     for(int i=1;i<=n;i++){
31         for(int j=1;j<=m;j++){
32             for(int c=0;c<=k;c++){
33                 if(i-1>0){
34                     (f[i][j][c][0]+=f[i-1][j][(c-a[i][j]+mod)%mod][1])%=p;
35                     (f[i][j][c][1]+=f[i-1][j][(c+a[i][j])%mod][0])%=p;
36                 } 
37                 if(j-1>0){
38                     (f[i][j][c][0]+=f[i][j-1][(c-a[i][j]+mod)%mod][1])%=p;
39                     (f[i][j][c][1]+=f[i][j-1][(c+a[i][j])%mod][0])%=p;
40                 } 
41             }
42         }
43     }
44     ll ans=0;
45     for(int i=1;i<=n;i++){
46         for(int j=1;j<=m;j++){
47             ans+=f[i][j][0][1];
48             ans%=p;
49         }
50     }
51     printf("%lld",ans);
52     return 0;
53 }
——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
原文地址:https://www.cnblogs.com/Nelson992770019/p/11574534.html