给出N天的股价,能买入和卖出股票,但是任何时候手上最多持有一份股票.允许交易K次求最多的收益.

来源:互联网 发布:windows toolkit怎么用 编辑:程序博客网 时间:2024/04/30 19:56

poj8464股票买卖

我的:
这个题目的Dynamic programming 思想:
在a[i]之前找到最小的,然而最大的并不需要找,因为循环的时候回遍历出最大的dp值。
利用两个分开的额循环,找到i之前的最大值和i之后的最大值。
之后再遍历一遍找到两个和的最大值。

!!!:还需要注意的是,以后输入输出的时候还是用scanf和printf吧,这次真的认识到cin和scanf 的速度之差,以前书上看到的我还不相信,现在,以后都写scanf吧。

看图:
改之前和改之后的强烈差别,将近一倍

#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cstdio>#include<cstdlib>#include<set>#include<vector>#include<map>#include<queue>#include<stack>#include<deque>#include<list>#include<cmath>using namespace std;const int maxn=100000+10;int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n;        scanf("%d",&n);        int a[maxn];        for(int i=0;i<n;i++)            scanf("%d",&a[i]);        int dp1[maxn],dp2[maxn];        memset(dp1,0,sizeof(dp1));        memset(dp2,0,sizeof(dp2));        int mina=a[0];        dp1[0]=0;        for(int i=1;i<n;i++)        {            mina=min(mina,a[i]);            dp1[i]=max(dp1[i-1],a[i]-mina);//a[i]会一直走下去,尽管此时a[i]不是最大值,在a[i]前面已经找到了i之前的区间的最大值。        }        int maxa=a[n-1];        dp2[n-1]=0;        for(int i=n-2;i>=0;i--)        {            maxa=max(a[i],maxa);            dp2[i]=max(dp2[i+1],maxa-a[i]);        }//两个循环,一个找到i的左边的最大值,一个找到右边的最大值,最后找到他俩的最大值就行了。        int ans=0;        for(int i=0;i<n;i++)        {            if(dp1[i]+dp2[i]>ans)                ans=dp1[i]+dp2[i];        }        printf("%d\n",ans);    }    return 0;}

上面的K是等于2,但是当k > 2的情况,那又该怎么做呢?

九度OJ 1537 买卖股票(DP)

这里的n值不大:

题意:给出N天的股价,能买入和卖出股票,但是任何时候手上最多持有一份股票.允许交易K次求最多的收益.
思路:设dp[i][j]为前i天交易j次的最大收益, 这题和CF391F1几乎一样,只不过CF上的数据量比较大..
那么dp[i][j] = max(dp[k][j - 1] - a[k + 1] + a[i], dp[i - 1][j]) 0<=k

#include <cstdio>#include <memory.h>#include <algorithm>using namespace std;const int MAX = 1001;int n, k;int dp[MAX][MAX];int a[MAX];int main(int argc, char const *argv[]){    while(scanf("%d%d", &n, &k) == 2){        for(int i = 1; i <= n; ++i){            scanf("%d", &a[i]);        }        memset(dp, 0, sizeof(dp));        for(int j = 1; j <= k; ++j){            int maxv = dp[0][j - 1] - a[1];            for(int i = 1; i <= n; ++i){                dp[i][j] = max(dp[i - 1][j], maxv + a[i]);                maxv = max(maxv, dp[i][j - 1] - a[i + 1]);            }        }        printf("%d\n", dp[n][k]);    }    return 0;}

但是当N更大的时候应该怎么做呢?

codeforces 391 F1F2F3;
In subproblem F1 (8 points), n will be between 1 and 3000, inclusive.
In subproblem F2 (15 points), n will be between 1 and 100000, inclusive.
In subproblem F3 (10 points), n will be between 1 and 4000000, inclusive.

目前还不会。。。

0 0
原创粉丝点击