UVA 1412 Fund Management(DP)

题意是m天n只股票给你买卖,然后要求最后一天结束后不持有任何股票,剩余钱最多,每天只能买和卖一手某种股票。还有各种限制条件,比如总持有股票数不能超过k,每个股票持有手数最多不能超过多少啊。。

看大白书的题,DP思路很好想,就是到第i天手里买了哪几种股票组合以及手数,拥有现金的最多。这样递推到最后一天手里没有股票所拥有的现金就是答案。

首先状态数是多少?书上写的是最多9^8,实际上远远没有那么多,因为每个股票手数之和最大也不超过8,而且股票总数也最多只有8个,我写了个dfs程序算了下,不超过13000种状态。然后状态转移也很好想,但是不好写,因为涉及到这个数字对应哪种状态,的确可以用9进制去写,不过比较麻烦,可以说不是二进制的状态都不好写,因为要转化成那个进制的数字。

学习了用map, int>的写法,话说vector原来自定义了<号么?还是因为int定义了小于号所以vector也相当于定义了?这点还真不太懂,直接dfs暴力枚举每种可能的状态,然后在map里编好号,再保存每个状态的各种可能转移到的状态,这里改了vector就可以直接在map里找,实在方便。代码的思路跟书上没差太多,不过没照抄。

AC代码:

//#pragma comment(linker, "/STACK:102400000,102400000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
#define eps 1e-4
#define NMAX 200005
#define MOD 1000000009
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1)
template
inline void scan_d(T &ret)
{
    char c;
    int flag = 0;
    ret=0;
    while(((c=getchar())<'0'||c>'9')&&c!='-');
    if(c == '-')
    {
        flag = 1;
        c = getchar();
    }
    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
    if(flag) ret = -ret;
}
double price[10][105],c;
int k[10];
char name[10][10];
vector< vector >v;
map, int>mp;
int m,n,K,buy[13000][10],sell[13000][10];
double dp[105][13000];
int pre[105][13000][3];
int sig(double x){return (x>eps) - (x<-eps);}
void dfs(int w, vector& lots, int totlot)
{
    if(w == n)
    {
        lots[n] = totlot;
        mp[lots] = v.size();
        v.push_back(lots);
        return;
    }
    for(int i = 0; i <= k[w] && i+totlot <= K; i++)
    {
        lots[w] = i;
        dfs(w+1, lots, totlot+i);
    }
}

void init()
{
    v.clear();
    mp.clear();
    vectorp(n+1);
    dfs(0,p,0);
    for(int i = 0; i < v.size(); i++)
    {
        int sum = v[i][n];
        for(int j = 0; j < n; j++)
        {
            buy[i][j] = sell[i][j] = -1;
            if(v[i][j] < k[j] && sum < K)
            {
                vectortemp = v[i];
                temp[j]++;
                temp[n]++;
                buy[i][j] = mp[temp];
            }
            if(v[i][j] > 0)
            {
                vectortemp = v[i];
                temp[j]--;
                temp[n]--;
                sell[i][j] = mp[temp];
            }
        }
    }
}
void print(int day, int state)
{
    if(day == 0) return;
    print(day-1, pre[day][state][0]);
    if(pre[day][state][2] == 0) printf("HOLD\n");
    else if(pre[day][state][2] > 0) printf("BUY %s\n",name[pre[day][state][1]]);
    else printf("SELL %s\n",name[pre[day][state][1]]);
}
int main()
{
#ifdef GLQ
    freopen("input.txt","r",stdin);
//    freopen("o4.txt","w",stdout);
#endif // GLQ
    while(~scanf("%lf%d%d%d",&c,&m,&n,&K))
    {
        for(int i = 0; i < n; i++)
        {
            int pp;
            scanf("%s%d%d",name[i],&pp,&k[i]);
            for(int j = 0; j < m; j++)
            {
                scanf("%lf",&price[i][j]);
                price[i][j] *= pp;
            }
        }
        init();
        for(int i = 0; i <= m; i++)
            for(int j = 0; j < v.size(); j++)
            {
                dp[i][j] = -(1<<30);
            }
        dp[0][0] = c;
        for(int i = 0; i < m; i++)
            for(int j = 0; j < v.size(); j++) if(sig(dp[i][j]) >= 0)
            {
                if(dp[i][j] >= dp[i+1][j])
                {
                    dp[i+1][j] = dp[i][j];
                    pre[i+1][j][0] = j;
                    pre[i+1][j][2] = 0;
                }
                for(int ii = 0; ii < n; ii++)
                {
                    if(sig(dp[i][j]-price[ii][i]) >= 0 && buy[j][ii] != -1 && dp[i+1][buy[j][ii]] < dp[i][j]-price[ii][i])
                    {
                        dp[i+1][buy[j][ii]] = dp[i][j] - price[ii][i];
                        pre[i+1][buy[j][ii]][0] = j;
                        pre[i+1][buy[j][ii]][1] = ii;
                        pre[i+1][buy[j][ii]][2] = 1;
                    }
                    if(sell[j][ii] != -1 && dp[i+1][sell[j][ii]] < dp[i][j]+price[ii][i])
                    {
                        dp[i+1][sell[j][ii]] = dp[i][j] + price[ii][i];
                        pre[i+1][sell[j][ii]][0] = j;
                        pre[i+1][sell[j][ii]][1] = ii;
                        pre[i+1][sell[j][ii]][2] = -1;
                    }
                }
            }
        printf("%.2lf\n",dp[m][0]);
        print(m,0);
    }
    return 0;
}



你可能感兴趣的:(DP)