题目大意我就不说了,都是中文,好懂的。比赛的时候我写的代码是即超时又爆内存的,不知道当时是怎么 的突发奇想就去写了,可能是想到别的题也写不出来所以就把这道题的明知道过不了的方法写了。。。
解题思路:是对每个点记录其的差的。首先就是优化内存,dp[i][j][x]记录的是在点mp[i][j]其人和剑的能量的差值为x的个数。此题重点在于怎样写使得x的值是轮流的,假设当前的人的能量值为a,剑的能量值为b,所以其差值为a-b,这次在点mp[i-1][j]的时候其能量值是加在a上的,那么在点mp[i][j]点的时候能量值就应该加在b上了,就是一个轮流的思想,所以我们要做减法,即在kmp=a[i][j]-x,然后dp[i][j][kmp]=dp[i-1][j][x]+dp[i][j-1][x],例如x是由a-b得到的,在下一个点用a[i][j](设值为c)-x即代表为c+b-a,就反过来了,再有一个点a[i+1][j](设为d)-x又变为a+d-b-c,这就是轮着转换的思想,刚好实现了剑的能量和人的能量间隔相加,好巧妙的
啊!再有一点就是时间的优化,其实大家一想其实都可以想到的,这就不用啰嗦了,直接复杂度为o(n*n*11);
下面的是代码,惭愧啦!本来是惯用c++的,但是最近快要考试了,要考java可是什么都不会,然后又不知道该用java做点什么,然后就决定用java刷一段时间的题看看,其实看看自己的代码还是c++,值不过输入输出方式不对而且。。。
import java.util.*; public class Main { public static void main(String args[]) { Scanner cin=new Scanner(System.in); int test,n,m,i,j,k; int N=500; char [] s1=new char[N]; int [][] a=new int [N][N]; int [][][]dp=new int[N][N][12]; String s; int Mod=1000000007; test=cin.nextInt(); for(int ror=1;ror<=test;++ror) { n=cin.nextInt(); m=cin.nextInt(); cin.nextLine(); for(i=1; i<=n; ++i) { s=cin.nextLine(); s1=s.toCharArray(); for(j=0; j<s1.length; ++j) a[i][j+1]=s1[j]-'0'; } for(i=0; i<=n; ++i) for(j=0; j<=m; ++j) for(k=0;k<11; k++) dp[i][j][k]=0; int ans=0,kmp=0; for(i=1; i<=n;++i) for(j=1;j<=m; ++j) { dp[i][j][a[i][j]]=1; for(k=0; k<11; k++) { kmp=a[i][j]-k; kmp%=11; if(kmp<0) kmp+=11; // System.out.println(kmp); // System.out.println(i+" "+j+" "+k+" "+dp[i][j][k]); dp[i][j][kmp]+=(dp[i-1][j][k]+dp[i][j-1][k])%Mod; } ans+=dp[i][j][0]; // dp[i][j][0]=0; ans%=Mod; // System.out.println("sn"+ans); } System.out.println("Case "+ror+": "+ans); } } }