动态规划专题:传纸条

题目描述:

小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,座标(1,1),小轩坐在矩阵的右下角,座标(m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。
在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。
还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用0表示),可以用一个0-100的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度只和最大。现在,请你帮助小渊和小轩找到这样的两条路径。

大致思路:

第一想法是两次动态规划,第二次先把第一次的路径删除之后进行,但是两条路径相交的问题就没法处理了。

于是采用四维动规的思想,f[i][j][k][l]表示经过点i,j和点k,l所能得到的最大值,显然i=k和k=l的情况是不可取的,这个状态可以从四个状态转移过来,分别是上下左右。

可以采取一个小优化,用一个新的维度o记录步数,这样只需要记录x座标即可,就将四维优化成了三维动规了。

代码:

#include <iostream>
#include <cstring>


using namespace std;


int f[101][51][51],a[51][51],n,m;


int main() {
cin>>m>>n;
memset(f,0,sizeof(f));
for (int i = 1; i<=m; i++) {
for (int j = 1; j<=n; j++) 
cin>>a[i][j];
}
for(int k=1;k<=m+n-3;++k)
for(int x1=1;x1<=min(n,k+1);++x1)
for(int x2=1;x2<=min(n,k+1);++x2) {
f[k][x1][x2]=max(max(f[k-1][x1][x2],f[k-1][x1-1][x2]),max(f[k-1][x1][x2-1],f[k-1][x1-1][x2-1]));
if (x1==x2) f[k][x1][x2]+=a[k-x1+2][x1]; 
else f[k][x1][x2]+=(a[k-x1+2][x1]+a[k-x2+2][x2]);
} 
cout<<f[m+n-3][n][n-1];
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章