UVA1412 基金管理 Fund Management

22 篇文章 0 订阅
  • 状态压缩,一个状态是一个九进制数,vector<vector >states对状态编号(编号>状态),map<vector,int>id(状态>编号)紫书的代码里用一个vector< int >表示状态,巧妙。
  • 预处理编号为状态s下对股票i的进行买卖操作后得到的状态编号。
#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
using namespace std;
const int maxst = 5e5,maxm = 105;
const double inf = 1e8;
int n,kk,si,m;//kk:最大持有数
int buy_next[maxst][12],sell_next[maxst][12],k[12];
double d[maxm][maxst],c,price[12][maxm];
int opt[maxm][maxst],pre[maxm][maxst];//存方案,opt:这一天此状态买还是卖,哪一只股票。pre:这一天转移子上一天的状态编号
vector<vector<int> >states;
map<vector<int>,int>id;
char name[10][30];
void dfs(int stock,vector<int>& lots,int totlot)//给状态编号
{
    if(stock==n){
        id[lots]=states.size();//状态lots的编号
        states.push_back(lots);
    }
    else for(int i=0;i<=k[stock]&&i+totlot<=kk;i++){
        lots[stock]=i;
        dfs(stock+1,lots,totlot+i);
    }
}
void intt()
{
    for(int s=0;s<states.size();s++){
        int totlot=0;
        for(int i=0;i<n;i++)
            totlot+=states[s][i];
        for(int i=0;i<n;i++){
            sell_next[s][i]=buy_next[s][i]=-1;
            if(states[s][i]<k[i]&&totlot<kk){
                vector<int> newstate = states[s];
                newstate[i]++;
                buy_next[s][i] = id[newstate];
            }
            if(states[s][i]>0){
                vector<int> newstate = states[s];
                newstate[i]--;
                sell_next[s][i] = id[newstate];
            }
        }
    }
}
void update(int day,int s0,int s,double v,int o)
{
    if(v>d[day+1][s]){
        d[day+1][s] = v;
        opt[day+1][s] = o;
        pre[day+1][s] = s0;
    }
}
double dp()
{
	states.clear();
	id.clear();
	vector<int> lot(n);
	dfs(0,lot,0);
	intt();	
    for(int i=0;i<=m;i++)
        for(int j=0;j<states.size();j++)
           d[i][j] = -inf;
    d[0][0] = c;
    for(int day=0;day<m;day++){
        for(int i=0;i<states.size();i++){
                double v = d[day][i];
                if(v < -1)//无意义的状态
                    continue;
                update(day,i,i,v,0);//hold
            for(int j=0;j<n;j++){
                if(buy_next[i][j]>=0 && v>=price[j][day+1])
                    update(day,i,buy_next[i][j],v-price[j][day+1],j+1);//买一手
                if(sell_next[i][j]>=0)
                    update(day,i,sell_next[i][j],v+price[j][day+1],-j-1);//卖一手
            }
        }
    }
    return d[m][0];
}
void print(int day,int s)
{
    if(day==0) return ;
    print(day-1,pre[day][s]);
	if(opt[day][s]==0)printf("HOLD\n");
	else if(opt[day][s]>0)printf("BUY %s\n",name[opt[day][s]-1]);
	else printf("SELL %s\n",name[-(opt[day][s]+1)]);
}
int main()
{
//	freopen("1.txt","w",stdout);
    string str;
    dp();
    while(cin>>c>>m>>n>>kk)
    {
		for(int i=0;i<n;i++)
		{
			scanf("%s%d%d",name[i],&si,&k[i]);
			for(int j=1;j<=m;j++)
			{
				double temp;
				scanf("%lf",&temp);
				price[i][j]=temp*(double)si;
			}
		}
        printf("%.2lf\n",dp());
        print(m,0);
        cout<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈希表扁豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值