想了很久都没想明白为什么状态总数不超过13000种,找到了递推式,但觉得只能通过dp或枚举得到。
事先计算出所有可能的状态,然后构造一个状态转移表。
把程序每一个大的步骤都写在函数内,结构清晰。
频繁使用的函数封装起来,如update。
保存路径多开一个空间,这样找路径时就可以O(n)而不是O(n^2)。
递归倒序打印。
刷表法dp前要全部赋值一遍,代表从未访问过。
把一股的价格改为一手的价格,化简了问题。
#include<bits/stdc++.h>
#define maxn 110
#define INF 0X3F3F3F3F
using namespace std;
double C;
int M,N,K;
char name[10][maxn];
int k[maxn];
double d[10][maxn];
map<vector<int>,int>ID;
vector<vector<int> >states;
double bn[15000][10];
double sn[15000][10];
double dp[maxn][15000];
int opt[maxn][15000],pre[maxn][15000];
void dfs(int day,vector<int>& lots,int tot)
{
if(day==N)
{
ID[lots]=states.size();
states.push_back(lots);
return;
}
for(int i=0;i<=k[day]&&i+tot<=K;i++)
{
lots[day]=i;
dfs(day+1,lots,tot+i);
}
}
void ud(int day,int s,int s2,double v,int o)
{
if(v>dp[day+1][s2])
{
dp[day+1][s2]=v;
opt[day+1][s2]=o;
pre[day+1][s2]=s;
}
}
void print_ans(int day,int s)
{
if(day==0) return;
print_ans(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()
{
while(scanf("%lf %d %d %d",&C,&M,&N,&K)!=EOF)
{
double temp;
for(int i=0;i<N;i++)
{
scanf("%s %lf %d",name[i],&temp,&k[i]);
for(int j=0;j<M;j++)
{
scanf("%lf",&d[i][j]);
d[i][j]*=temp;
}
}
ID.clear();
states.clear();
vector<int>lots(N);
dfs(0,lots,0);
for(unsigned int s=0;s<states.size();s++)
{
int tot=0;
for(int i=0;i<N;i++)
{
bn[s][i]=sn[s][i]=-1;
tot+=states[s][i];
}
for(int i=0;i<N;i++)
{
if(states[s][i]<k[i]&&tot<K)
{
vector<int> news=states[s];
news[i]++;
bn[s][i]=ID[news];
}
if(states[s][i]>0)
{
vector<int> news=states[s];
news[i]--;
sn[s][i]=ID[news];
}
}
}
for(int day=0;day<=M;day++)
for(unsigned int s=0;s<states.size();s++) dp[day][s]=-INF;
dp[0][0]=C;
for(int day=0;day<M;day++)
for(unsigned int s=0;s<states.size();s++)
{
double v=dp[day][s];
if(v<-1) continue;
ud(day,s,s,v,0);
for(int i=0;i<N;i++)
{
if(bn[s][i]>=0&&v>=d[i][day]-1e-3)
ud(day,s,bn[s][i],v-d[i][day],i+1);
if(sn[s][i]>=0)
ud(day,s,sn[s][i],v+d[i][day],-i-1);
}
}
printf("%.2lf\n",dp[M][0]);
print_ans(M,0);
}
return 0;
}