NYOJ 61(传纸条)

 

NYOJ 61 传纸条是一个双线DP的题:

从矩阵的左上角(1,1)点到矩阵的右下角(m,n)点找到两条不相交的路径使其值最大,

题中是从(1,1)到(m,n)走一次,再从(m,n)到(1,1)走一次,我们可以等价变形

一下,变为:同时从(1,1)走向(m,n)找两条路,且这两条路不相交,同时走!

假设有两个人在走,一个人的坐标为(x1,y1),另一个人的坐标为(x2,y2),有题中规定

只能向下或向右走,则可得状态转移方程:

f(x1,y1,x2,y3)  =  max { f(x1-1,y1,x2-1,y2)  ,f(x1-1,y1,x2,y-1),  f(x1,y1-1,x2-1,y2),  f(x1,y1-1,x2,y2-1)} + map[x1][y1] + map[x2][y2]

(map中存放同学的好心度,相当于权值)

 

这样写的话  时间复杂度会是O(n^4),比较大容易超时,改进:

因为 两个人是同时走的所以 每次都是同时移动一格:因此有   x1+y1==x2+y2 == k

则状态方程可以改为:

 

f(k,x1,x2) = ma{  f(k-1,x1,x2),  f(k-1,x-1,x2) ,f(k-1,x1,x2-1),  f(k-1,x1-1,x2-1)  }  + map[x1][k-x1] + map[x2][k-x2]

 

本题代码:

 

 

View Code
 1  

 2 #include<stdio.h>

 3 #include<string.h>

 4 

 5 int a[201][101][101];

 6 int map[101][101];

 7 

 8 int max(int n1,int n2,int n3,int n4)

 9 {

10    int s,d;

11    s = n1>n2?n1:n2;

12    d = n3>n4?n3:n4;

13    s = s>d?s:d;

14    return s;

15 }

16 

17 int slove(int m,int n)

18 {

19   int x1,y1,x2,y2,k;

20   for(k=2;k<=m+n;++k)

21    for(x1=1;x1<=m;++x1)

22     for(x2=1;x2<=m;++x2)

23      {

24        y1=k-x1;

25        y2=k-x2;

26        if(y1<0 || y2<0 || y1>n || y2>n)continue;

27        if(y1==y2)continue;

28        a[k][x1][x2]=max(a[k-1][x1][x2],a[k-1][x1-1][x2],

29                         a[k-1][x1][x2-1],a[k-1][x1-1][x2-1])

30                         +map[x1][y1]+map[x2][y2];

31      }

32    return a[m+n-1][m][m-1];

33 }

34 

35 int main()

36 {

37   int t,m,n,i,j;

38   scanf("%d",&t);

39   while(t--)

40   {

41     memset(a,0,sizeof(a));

42     scanf("%d%d",&m,&n);

43     for(i=1;i<=m;++i)

44      for(j=1;j<=n;++j)

45       scanf("%d",&map[i][j]);

46     printf("%d\n",slove(m,n));

47   }

48   return 0;

49 }

50 

51         

 

你可能感兴趣的:(OJ)