zoukankan      html  css  js  c++  java
  • 洛谷P1373 小a和uim之大逃离 (DP)

    洛谷P1373 小a和uim之大逃离

    题目背景

    小a和uim来到雨林中探险。突然一阵北风吹来,一片乌云从北部天边急涌过来,还伴着一道道闪电,一阵阵雷声。刹那间,狂风大作,乌云布满了天空,紧接着豆大的雨点从天空中打落下来,只见前方出现了一个披头散发、青面獠牙的怪物,低沉着声音说:“呵呵,既然你们来到这,只能活下来一个!”。小a和他的小伙伴都惊呆了!

    题目描述

    瞬间,地面上出现了一个n*m的巨幅矩阵,矩阵的每个格子上有一坨0~k不等量的魔液。怪物各给了小a和uim一个魔瓶,说道,你们可以从矩阵的任一个格子开始,每次向右或向下走一步,从任一个格子结束。开始时小a用魔瓶吸收地面上的魔液,下一步由uim吸收,如此交替下去,并且要求最后一步必须由uim吸收。魔瓶只有k的容量,也就是说,如果装了k+1那么魔瓶会被清空成零,如果装了k+2就只剩下1,依次类推。怪物还说道,最后谁的魔瓶装的魔液多,谁就能活下来。小a和uim感情深厚,情同手足,怎能忍心让小伙伴离自己而去呢?沉默片刻,小a灵机一动,如果他俩的魔瓶中魔液一样多,不就都能活下来了吗?小a和他的小伙伴都笑呆了!

    现在他想知道他们都能活下来有多少种方法。

    输入输出格式

    输入格式:

    第一行,三个空格隔开的整数n,m,k

    接下来n行,m列,表示矩阵每一个的魔液量。同一行的数字用空格隔开。

    输出格式:

    一个整数,表示方法数。由于可能很大,输出对1 000 000 007取余后的结果。

    输入输出样例

    输入样例#1:

    2 2 3
    1 1
    1 1

    输出样例#1:

    4

    说明

    【题目来源】

    lzn改编

    【样例解释】

    样例解释:四种方案是:(1,1)->(1,2),(1,1)->(2,1),(1,2)->(2,2),(2,1)->(2,2)。

    【数据范围】

    对于20%的数据,n,m<=10,k<=2

    对于50%的数据,n,m<=100,k<=5

    对于100%的数据,n,m<=800,1<=k<=15

    Solution

    这道题十分的皮?
    因为每次只能从正上和正左转移过来,所以可以看出是递推,可是每次都要换一个人,怎么表示?
    没事,我们可以把它记录到状态中,(dp[i][j][0])表示((i,j))这个点由小a拿的方案数,同理(dp[i][j][1])表示((i,j))这个点由uim拿的方案数,那么怎么表示让他们拿的药水一样多呢?
    两遍dp??? 会T飞,下一个
    是的,一遍dp,再加一维状态,两个人所收集的药水的差值,至此,dp数组设计完毕,下面是思考状态转移环节

    [dp[i][j][t][0]+=dp[i-1][j][t-a[i][j]][1] ]

    这里的意思是如果当前是小a选,那么差值会增大,由(t-a[i][j] o t),所以方案数要加起来,下面同理

    [dp[i][j][t][0]+=dp[i][j-1][t-a[i][j]][1] ]

    [dp[i][j][t][1]+=dp[i-1][j][t+a[i][j]][0] ]

    差值变小,由(t+a[i][j] o t)

    [dp[i][j][t][1]+=dp[i][j-1][t+a[i][j]][0] ]

    因为每次超过k就会清零,注意是超过,所以为了方便,初始化k++
    除此之外,因为小a从哪里开始都可以,所以初始化

    dp[i][j][a[i][j]][0]=1
    

    记住,状态转移的时候要取模,还有由于相见可能会是负数,所以(t-a[i][j]+k)%k防止越界

    Code

    #include<bits/stdc++.h> 
    #define in(i) (i=read())
    #define lol long long
    #define rg register
    #define il extern inline
    using namespace std;
    const int N=810,mod=1000000007;
    int read() {
    	int ans=0,f=1; char i=getchar();
    	while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
    	while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48),i=getchar();
    	return ans*f;
    }
    lol ans;
    int n,m,k;
    int a[N][N],dp[N][N][16][2];
    int main()
    {
    	in(n);in(m);in(k);k++;
    	for(rg int i=1;i<=n;i++)
    		for(rg int j=1;j<=m;j++)
    			in(a[i][j]),dp[i][j][a[i][j]%k][0]=1;
    	for(rg int i=1;i<=n;i++) {
    		for(rg int j=1;j<=m;j++) {
    			for(rg int t=0;t<k;t++) {
    				(dp[i][j][t][0]+=dp[i-1][j][(t-a[i][j]+k)%k][1])%=mod;
    				(dp[i][j][t][0]+=dp[i][j-1][(t-a[i][j]+k)%k][1])%=mod;
    				(dp[i][j][t][1]+=dp[i-1][j][(t+a[i][j])%k][0])%=mod;
    				(dp[i][j][t][1]+=dp[i][j-1][(t+a[i][j])%k][0])%=mod;
    			}
    		}
    	}
    	for(rg int i=1;i<=n;i++)
    		for(rg int j=1;j<=m;j++)
    			(ans+=1ll*dp[i][j][0][1])%=mod;//答案记得开long long
    	cout<<ans<<endl;
    }
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    Maven关于web.xml中Servlet和Servlet映射的问题
    intellij idea的Maven项目运行报程序包找不到的错误
    修改Maven项目默认JDK版本
    刷题15. 3Sum
    刷题11. Container With Most Water
    刷题10. Regular Expression Matching
    刷题5. Longest Palindromic Substring
    刷题4. Median of Two Sorted Arrays
    刷题3. Longest Substring Without Repeating Characters
    刷题2. Add Two Numbers
  • 原文地址:https://www.cnblogs.com/real-l/p/9720815.html
Copyright © 2011-2022 走看看