- 状态压缩,一个状态是一个九进制数,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;
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];
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();
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);
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()
{
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;
}