1. 程式人生 > 其它 >扣分後的最大得分

扣分後的最大得分

Leetcode 1937.扣分後的最大得分

題目

給你一個m*n的整數矩陣points(下標從0開始)。一開始你的得分為0,你想最大化從矩陣中得到的分數。
你的得分方式為:每一行中選取一個格子,選中座標為(r,c)的格子會給你的總得分增加points[r][c]。
然而,相鄰行之間被選中的格子如果隔得太遠,你會失去一些得分。對於相鄰行r和r+1(其中0 <=r<m-1),選中座標為(r,c1)和(r+1,c2)的格子,你的總得分減少abs(c1-c2)。
請你返回你能得到的最大得分。

abs(x)定義為:

  • 如果x>=0,那麼值為x。
  • 如果x<0,那麼值為-x。

題解

其實看到解釋abs定義時就感覺有點東西了,因為總不會有人不知道abs的意思吧!
典型動態規劃題,我一來就搞了個很樸素的dp公式。

 int f[maxx][maxx];
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++){
               f[0][j]=p[0][j];
               for(int k=0;k<n;k++){
                    f[i][j]=max(f[i][j],p[i][j]+f[i-1][k]-abs(j-k));
               }
            }

哈哈,三重迴圈,我不死誰死?(即答:被o(n^3)凌虐的電腦)
然後再看一眼題目裡的abs。悟了,這就拆,這就拆。

class Solution {
public:
    long long maxPoints(vector<vector<int>>& p) {
        int m=p.size(),n=p[0].size();
        long long f[maxx];
        for(int j=0;j<n;j++) f[j]=p[0][j];
        long long l[maxx],r[maxx];
        for(int i=1;i<m;i++) {
            l[0]=f[0];
            for(int j=1;j<n;j++){//左邊
                l[j]=max(l[j-1],f[j]+j);
            }
            r[n-1]=f[n-1]-(n-1);
            for(int j=n-2;j>=0;j--){//右邊
                r[j]=max(r[j+1],f[j]-j);
            }
            for(int j=0;j<n;j++)
                f[j]=p[i][j]+max(l[j]-j,r[j]+j);
        }
        long long ans=0;
        for(int j=0;j<n;j++) ans=max(ans,f[j]);
        return ans;
    }
};