算法提高--数字三角形模型

https://www.acwing.com/problem/content/900/

 

 

 注意处理边界即可。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N=510;
 6 int a[N][N],f[N][N];
 7 int n;
 8 int main()
 9 {
10     cin>>n;
11     for(int i=1;i<=n;i++){
12         for(int j=1;j<=i;j++){
13             cin>>a[i][j];
14         }
15     }
16     for(int i=1;i<=n;i++){
17         for(int j=1;j<=i;j++){
18             if(j==1){
19                 f[i][j]=f[i-1][j]+a[i][j];
20             }else if(j==i){
21                 f[i][j]=f[i-1][j-1]+a[i][j];
22             }else{
23                 f[i][j]=max(f[i-1][j-1],f[i-1][j])+a[i][j];
24             }
25         }
26     }
27     int res=-10000*510;
28     for(int i=1;i<=n;i++) res=max(res,f[n][i]);
29     cout<<res;
30     return 0;
31 }

 

扩展1:将区域扩展为矩形----摘花生

https://www.acwing.com/problem/content/1017/

 

 

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N=110;
 6 int w[N][N];
 7 int f[N][N];
 8 int main()
 9 {
10     int T;
11     cin>>T;
12     while(T--){
13         memset(f,0,sizeof f);
14         int n,m;
15         cin>>n>>m;
16         for(int i=1;i<=n;i++){
17             for(int j=1;j<=m;j++){
18                 cin>>w[i][j];
19             }
20         }
21         f[1][1]=w[1][1];
22         for(int i=1;i<=n;i++){
23             for(int j=1;j<=m;j++){
24                 if(i!=1) f[i][j]=max(f[i][j],f[i-1][j]+w[i][j]);
25                 if(j!=1) f[i][j]=max(f[i][j],f[i][j-1]+w[i][j]);
26             }
27         }
28         cout<<f[n][m]<<endl;
29     }
30     return 0;
31 }

 

扩展2:最低通行费,给定步数为2*n-1,而区域大小为n*n,故同摘花生。

    但因为目标是获得最小值,故注意初始化。

https://www.acwing.com/problem/content/1020/

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 110,INF = 0x3f3f3f3f;
 6 int w[N][N];
 7 int f[N][N];
 8 int main()
 9 {
10     int n;
11     cin>>n;
12     for(int i=1;i<=n;i++){
13         for(int j=1;j<=n;j++){
14             cin>>w[i][j];
15         }
16     }
17     for(int i=1;i<=n;i++){
18         for(int j=1;j<=n;j++){
19             f[i][j]=INF;
20             if(i==1&&j==1) f[i][j]=w[i][j];
21             else{
22                 if(i!=1) f[i][j]=min(f[i][j],f[i-1][j]+w[i][j]);
23                 if(j!=1) f[i][j]=min(f[i][j],f[i][j-1]+w[i][j]);
24             }
25         }
26     }
27     cout<<f[n][n];
28     return 0;
29 }

 

扩展3:方格取数,或称为传纸条,题设同样为矩形,两条从左上到右下的路线,因为权值均大于0,所以二者都是两条路线不重合。

    目标是使得权值最大。

https://www.acwing.com/problem/content/1029/

  

只需要在每次转移的时候判断两点是否重合即可。

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 15;
 6 int w[N][N];
 7 int f[N][N][N][N];
 8 
 9 int main()
10 {
11     int n;
12     cin>>n;
13     int a,b,c;
14     while(cin>>a>>b>>c,a||b||c) w[a][b]=c;
15     for(int i1=1;i1<=n;i1++){
16         for(int j1=1;j1<=n;j1++){
17             for(int i2=1;i2<=n;i2++){
18                 for(int j2=1;j2<=n;j2++){
19                     int & x= f[i1][j1][i2][j2];
20                     int t=w[i1][j1];
21                     if(i1!=i2&&j1!=j2)
22                         t+=w[i2][j2];
23                     x=max(x,f[i1-1][j1][i2-1][j2]+t);
24                     x=max(x,f[i1][j1-1][i2-1][j2]+t);
25                     x=max(x,f[i1-1][j1][i2][j2-1]+t);
26                     x=max(x,f[i1][j1-1][i2][j2-1]+t);
27 
28                 }
29             }
30         }
31     }
32     cout<<f[n][n][n][n]<<endl;
33     return 0;
34 }

 

 

又因为步数+横坐标即可唯一确定位置,所以我们可以优化掉一维。

f [ k ] [ i1 ] [ i2 ]表示经过k步后,第一条停在( i1 , k - i1)的位置,第二条停在( i2 , k - i2)的位置。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 15;
 6 int w[N][N];
 7 int f[N*2][N][N];
 8 
 9 int main()
10 {
11     int n;
12     cin>>n;
13     int a,b,c;
14     while(cin>>a>>b>>c,a||b||c) w[a][b]=c;
15     for(int k=2;k<=n+n;k++){
16         for(int i1=1;i1<=n;i1++){
17             for(int i2=1;i2<=n;i2++){
18                 int j1=k-i1;
19                 int j2=k-i2;
20                 int & x= f[k][i1][i2];
21                 int t=w[i1][j1];
22                 if(i1!=i2&&j1!=j2)
23                     t+=w[i2][j2];
24                 x=max(x,f[k-1][i1-1][i2-1]+t);
25                 x=max(x,f[k-1][i1-1][i2]+t);
26                 x=max(x,f[k-1][i1][i2-1]+t);
27                 x=max(x,f[k-1][i1][i2]+t);
28             }
29         }
30     }
31     cout<<f[n+n][n][n]<<endl;
32     return 0;
33 }

 

posted on 2021-06-26 10:28  greenofyu  阅读(46)  评论(0编辑  收藏  举报