计蒜客 T1227 大盗阿福

解法一

状态表示:

(f(i,0)):表示考虑前(i)家商店且不窃取第(i)家店铺的情况下所获得的最大价值。

(f(i,1)):表示考虑前(i)家商店且窃取第(i)家店铺的情况下所获得的最大价值。

状态转移:

[f(i,0)=max(f(i-1,0),f(i-1,1)) \ f(i,1)=f(i-1,0)+w[i] ]

const int N=1e5+10;
int w[N];
int f[N][2];
int n;

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;

        for(int i=1;i<=n;i++) cin>>w[i];

        f[1][0]=0;
        f[1][1]=w[1];
        for(int i=2;i<=n;i++)
        {
            f[i][0]=max(f[i-1][0],f[i-1][1]);
            f[i][1]=f[i-1][0]+w[i];
        }

        cout<<max(f[n][0],f[n][1])<<endl;
    }
    //system("pause");
    return 0;
}

解法二

如果只有一间房屋,则偷窃该房屋,可以偷窃到最高总金额。如果只有两间房屋,则由于两间房屋相邻,不能同时偷窃,只能偷窃其中的一间房屋,因此选择其中金额较高的房屋进行偷窃,可以偷窃到最高总金额。
如果房屋数量大于两间,应该如何计算能够偷窃到的最高总金额呢?对于第 (k ~ (k>2))间房屋,有两个选项:

  1. 偷窃第 (k) 间房屋,那么就不能偷窃第 (k−1) 间房屋,偷窃总金额为前 (k−2) 间房屋的最高总金额与第 (k) 间房屋的金额之和。
  2. 不偷窃第 (k) 间房屋,偷窃总金额为前 (k−1) 间房屋的最高总金额。

在两个选项中选择偷窃总金额较大的选项,该选项对应的偷窃总金额即为前 (k) 间房屋能偷窃到的最高总金额。

(dp[i]) 表示前 (i) 间房屋能偷窃到的最高总金额,那么就有如下的状态转移方程:

[dp[i]=max(dp[i-2]+w[i],dp[i-1]) ]

边界条件为:

[egin{cases} extit{dp}[0] = extit{nums}[0] & 只有一间房屋,则偷窃该房屋 \ extit{dp}[1] = max( extit{nums}[0], extit{nums}[1]) & 只有两间房屋,选择其中金额较高的房屋进行偷窃 end{cases} ]

最终的答案即为( extit{dp}[n-1]),其中 (n) 是数组的长度。

const int N=1e5+10;
int w[N];
int f[N];
int n;

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;

        for(int i=1;i<=n;i++) cin>>w[i];

        f[1]=w[1];
        f[2]=max(w[1],w[2]);
        for(int i=3;i<=n;i++)
            f[i]=max(f[i-2]+w[i],f[i-1]);  // 选或不选
        cout<<f[n]<<endl;
    }
    //system("pause");
    return 0;
}
原文地址:https://www.cnblogs.com/fxh0707/p/14669588.html