此题难点在于用九进制表示状态,并且转移
这里九进制用vector表示,再用map作为此状态特有的标记
此处用刷表法,每一种状态转移都经历一遍,最终状态就是正确答案,注意界限
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<stack> #include<queue> #include<algorithm> #include<set> #include<vector> #include<cmath> #define ll long long #define maxn 200 #define MST(vis,x) memset(vis,x,sizeof(vis)) #define INF 0x3f3f3f3f #define eps 1e-9 using namespace std; vector<vector<int>> states; map<vector<int>,int>ID; char name[maxn][maxn]; int s[maxn],k[maxn]; double price[maxn][maxn]; double c; int m,n,kk; int buy_next[15005][maxn]; int sell_next[15005][maxn]; 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]&&totlot+i<=kk;i++) { lots[stock]=i; dfs(stock+1,lots,totlot+i); } } void init() { vector<int>lots(n); states.clear(); ID.clear(); dfs(0,lots,0); 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++) { buy_next[s][i]=sell_next[s][i]=-1; if(states[s][i]<k[i]&&totlot<kk) { vector<int> newstates=states[s]; newstates[i]++; buy_next[s][i]=ID[newstates]; } if(states[s][i]>0) { vector<int>newstates=states[s]; newstates[i]--; sell_next[s][i]=ID[newstates]; } } } } double d[maxn][15005]; int opt[maxn][15005]; int prevv[maxn][15005]; void update(int day,int s,int s2,double v,int o) { if(v>d[day+1][s2]) { d[day+1][s2]=v; opt[day+1][s2]=o; prevv[day+1][s2]=s; } } double dp() { for(int day=0;day<=m;day++) for(int s=0;s<states.size();s++) d[day][s]=-INF; d[0][0]=c; for(int day=0;day<=m;day++) for(int s=0;s<states.size();s++) { double v=d[day][s]; if(v<-1)continue; update(day,s,s,v,0); for(int i=0;i<n;i++) { if(buy_next[s][i]>=0&&v>=price[i][day]-1e-3) update(day,s,buy_next[s][i],v-price[i][day],i+1); if(sell_next[s][i]>=0) update(day,s,sell_next[s][i],v+price[i][day],-i-1); } } return d[m][0]; } void print_ans(int day,int s) { if(day==0)return ; print_ans(day-1,prevv[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() { int t=0; while(scanf("%lf%d%d%d",&c,&m,&n,&kk)!=EOF) { if(t++>0)printf("\n"); for(int a=0;a<n;a++) { scanf("%s%d%d",name[a],&s[a],&k[a]); for(int i=0;i<m;i++) { scanf("%lf",&price[a][i]); price[a][i]*=s[a]; } } init(); double ans=dp(); printf("%.2f\n",ans); print_ans(m,0); } return 0; }
时间: 2024-10-28 22:48:26