cogs luogu 传纸条 2008年NOIP全国联赛提高组 WD

题目描述 Description

小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。

在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。

还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用0表示),可以用一个0-100的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度只和最大。现在,请你帮助小渊和小轩找到这样的两条路径。

输入描述 Input Description

输入的第一行有2个用空格隔开的整数m和n,表示班里有m行n列(1<=m,n<=50)。

接下来的m行是一个m*n的矩阵,矩阵中第i行j列的整数表示坐在第i行j列的学生的好心程度。每行的n个整数之间用空格隔开。

输出描述 Output Description

输出共一行,包含一个整数,表示来回两条路上参与传递纸条的学生的好心程度之和的最大值。

样例输入 Sample Input

3 3

0 3 9

2 8 5

5 7 0

样例输出 Sample Output

34

数据范围及提示 Data Size & Hint

30%的数据满足:1<=m,n<=10

100%的数据满足:1<=m,n<=50

 

dfs(sb)T7,正解是dp

dfs(纪念,也许剪枝不够或此题不可用dfs):

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define ll long long
 6 
 7 using namespace std;
 8 const int N=51;
 9 const int fistx[3]={0,1};
10 const int fisty[3]={1,0};
11 const int endx[3]={0,-1};
12 const int endy[3]={-1,0};
13 
14 ll a[N][N];
15 bool vis[N][N];
16 ll Answer;
17 ll answer;
18 ll n,m;
19 
20 ll read()
21 {
22     ll x=0;
23     char c=getchar();
24     while(c<'0'||c>'9')c=getchar();
25     while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
26     return x;
27 }
28 
29 void dfs_2(int x,int y)
30 {
31     if(x==1&&y==1)
32     {
33         Answer=max(Answer,answer);
34         return ;
35     }
36     for(int i=0;i<=1;i++)
37     {
38         int xx=x+endx[i];
39         int yy=y+endy[i];
40         if(!vis[xx][yy]&&xx>=0&&xx<=n&&yy>=0&&yy<=m)
41         {
42             vis[xx][yy]=1;
43             answer+=a[xx][yy];
44             dfs_2(xx,yy);
45             vis[xx][yy]=0;
46             answer-=a[xx][yy];
47         }
48     }
49 }
50 
51 void dfs_1(int x,int y)
52 {
53     if(x==n&&y==m)
54     {
55         dfs_2(x,y);
56         return ;
57     }
58     for(int i=0;i<=1;i++)
59     {
60         int xx=x+fistx[i];
61         int yy=y+fisty[i];
62         if(!vis[xx][yy]&&xx>=0&&xx<=n&&yy>=0&&yy<=m)
63         {
64             vis[xx][yy]=1;
65             answer+=a[xx][yy];
66             dfs_1(xx,yy);
67             vis[xx][yy]=0;
68             answer-=a[xx][yy];
69         }
70     }
71 }
72 
73 int main()
74 {
75     freopen("message.in","r",stdin);
76     freopen("message.out","w",stdout);
77     
78     n=read();
79     m=read();
80     
81     for(int i=1;i<=n;i++)
82         for(int j=1;j<=m;j++)
83             a[i][j]=read();
84 
85     dfs_1(1,1);
86     printf("%d",Answer);
87     return 0;
88 }

正解dp:

 1 #include <cstdio>
 2 #include<cmath>
 3 #include<iostream>
 4 
 5 using namespace std;
 6 
 7 int n,m,a[51][51],f[51][51][51];
 8 
 9 int main() 
10 {
11     scanf("%d%d",&n,&m);
12     for (int i = 1 ; i <= n ; i ++ )
13         for (int j = 1 ; j <= m ; j ++ )
14             scanf("%d",&a[i][j]);
15             
16     for (int i = 1 ; i <= n ; i ++ ) 
17     {
18         for (int j = 2 ; j <= m ; j ++ ) 
19         {
20             for(int k = i + 1 ; k < i + j && k <= n ; k ++ ) 
21             {
22                 int l = i + j - k ;
23                 f[i][j][k] =  max( max(f[i-1][j][k],f[i-1][j][k-1]), max(f[i][j-1][k],f[i][j-1][k-1]));
24                 f[i][j][k] += ( a[i][j] + a[k][l] ) ;
25             }
26         }
27     }
28     printf("%d",f[n-1][m][n]) ;
29 }

 

posted @ 2017-06-19 16:12  ioioioioioio  阅读(132)  评论(0编辑  收藏  举报