P1544 三倍经验

题意已经很清楚了,不再赘述。

解题思路
先不考虑乘三倍的情况。
将金字塔中每一个数看作一个点。

我们用 



,

dp 
i,j

  来表示走到第 

i 行第 

j 个点时走过的最大得分。
因为点(

,

i,j)是从点(


1
,

i−1,j)和点(


1
,


1
i−1,j−1)走来,所以易得状态转移方程式:




,

=
max

(




1
,

,




1
,


1
)
+


,

dp 
i,j

 =max(dp 
i−1,j

 ,dp 
i−1,j−1

 )+a 
i,j

 

然后考虑乘三倍的情况。
用 



,

,

dp 
i,j,l

  来表示走到第 

i 行第 

j 个点,乘 

l 次三倍时走过的最大得分。 结合不考虑乘三倍情况的状态转移方程式,易得最终状态转移方程式:




,

,

=
{



,

,

=
max

(




1
,

,

,




1
,


1
,

)
+


,

,
(

=
0
)



,

,

=
max

(



,

,

,




1
,

,


1
+


,

×
3
,




1
,


1
,


1
+


,

×
3
)
,
Otherwise.
dp 
i,j,l

 ={ 
dp 
i,j,l

 =max(dp 
i−1,j,l

 ,dp 
i−1,j−1,l

 )+a 
i,j

 ,(l=0)
dp 
i,j,l

 =max(dp 
i,j,l

 ,dp 
i−1,j,l−1

 +a 
i,j

 ×3,dp 
i−1,j−1,l−1

 +a 
i,j

 ×3),Otherwise.

 

以上是代码核心部分。 在搜索时要记得套两层循环(

j 和 

k),应为存在负数,所以不是乘三倍的次数越多越好。

k = min(k, n); // 不然可能导致没搜到k次,值为-3e9的情况。 
for(int j = 1; j <= n; ++ j)
    for(int l = 0; l <= k; ++ l)
        maxm = max(maxm, dp[n][j][l]); 
cout << maxm;
最后要记得在开始时把数组初始化。

AC 代码
#include
using namespace std;
typedef long long ll;
const int N = 105; 
int n, k;
ll a[N][N], dp[N][N][5505], maxm = -3e9;
signed main()
{
    //输入 
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n >> k;
    //初始化 
    for(int i = 1; i <= n; ++ i)
        for(int j = 0; j <= n; ++ j)
            for(int l = 0; l <= k; ++ l)
                dp[i][j][l] = -3e9; //a[i][j]最小是-1e9,还要乘3,所以设为-3e9(记得开long long)。 
    //边输入边做dp 
    for(int i = 1; i <= n; ++ i)
        for(int j = 1; j <= i; ++ j)
        {
            cin >> a[i][j];
            for(int l = 0; l <= k && l <= i; ++ l)
            {
                if(l == 0)
                    dp[i][j][l] = max(dp[i - 1][j][l], dp[i - 1][j - 1][l]) + a[i][j];
                else
                {
                    dp[i][j][l] = max(dp[i - 1][j][l], dp[i - 1][j - 1][l]) + a[i][j];
                    dp[i][j][l] = max(dp[i][j][l], max(dp[i - 1][j][l - 1], dp[i - 1][j - 1][l - 1]) + a[i][j] * 3);
                }
            }
        }
    k = min(k, n); // 不然可能导致没搜到k次,值为-3e9的情况。
    //搜索答案 
    for(int j = 1; j <= n; ++ j)
        for(int l = 0; l <= k; ++ l)
            maxm = max(maxm, dp[n][j][l]);
    //输出 
    cout << maxm;
    return 0;
}

你可能感兴趣的:(算法,图论,c++,数据结构)