UVA1412 基金管理 Fund Management题解
先看数据很小在
即考虑第
// 本程序会超时
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
using namespace std;
const double inf=1e30;
const int maxn=10;
const int maxm=110;
map<int,double> dp[maxm];
map<int,int> opt[maxm],prev[maxm];
int m,n,s[maxn],k[maxn],kk;
double c,price[maxn][maxm];
char name[maxn][10];
int encode(int* portfolio){//编码 por->h
int h=0;
for(int i=1;i<=n;i++) h=h*9+portfolio[i];//1->n 高位->低位
return h;
}
int decode(int h,int* portfolio){//解码 h->por
int totlot=0;
for(int i=n;i>=1;i--){
portfolio[i]=h%9;
totlot+=portfolio[i];
h/=9;
}
return totlot;
}
void update(int oldh,int day,int h,double v,int o){
if(dp[day].count(h)==0||v>dp[day][h]){//注意用count(h),因为可能之前没映射
dp[day][h]=v;
opt[day][h]=o;
prev[day][h]=oldh;
}
}
double Dp(){
int portfolio[maxn];
dp[1][0]=c;
for(int day=1;day<=m;day++){
for(map<int,double>::iterator it=dp[day].begin();it!=dp[day].end();it++){//迭代器
int h=it->first;
double v=it->second;
int totlot=decode(h,portfolio);
update(h,day+1,h,v,0);
for(int i=1;i<=n;i++){
if(portfolio[i]<k[i]&&totlot<kk&&v>=price[i][day]-1e-3){
portfolio[i]++;
update(h, day+1, encode(portfolio),v-price[i][day],i);
portfolio[i]--;
}
if(portfolio[i]>0){
portfolio[i]--;
update(h,day+1,encode(portfolio),v+price[i][day],-i);
portfolio[i]++;
}
}
}
}
return dp[m+1][0];
}
void print_ans(int day,int h){
if(day==1) return ;
print_ans(day-1,prev[day][h]);
if(opt[day][h]==0) printf("HOLD\n");
else if(opt[day][h]>0) printf("BUY %s\n",name[opt[day][h]]);
else printf("SELL %s\n",name[-opt[day][h]]);
}
int main() {
int kase=0;
while(cin>>c>>m>>n>>kk){
if(kase++>0) cout<<endl;
for(int i=1;i<=n;i++){
cin>>name[i]>>s[i]>>k[i];
for(int j=1;j<=m;j++) {
cin>>price[i][j];
price[i][j]*=s[i];
}
}
for(int i=1;i<=m;i++){ dp[i].clear(); opt[i].clear(); prev[i].clear(); }
double ans=Dp();
printf("%.2lf\n",ans);
print_ans(m+1,0);
}
return 0;
}
注意到虽然理论状态很多,但是实际可能满足题意的状态很少。故这里用到的思想就类似于 UVA12096 集合栈计算机 The SetStack Computer 这题了,我们可以提前计算出可能的所有状态并用 STL map,给他们编号,并且提前记录出下一个转移的对象,这样就可以大大提升程序效率了!
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const int maxn=10;
const int maxm=110;
const int maxstate=15000;
const int inf=0x3f3f3f3f;
double c,price[maxn][maxm];
int n,m,kk,kase=0;
char name[maxn][15];
int k[maxn],s[maxn];
double dp[maxm][maxstate];
int buy_next[maxstate][maxn],sell_next[maxstate][maxn];
int pre[maxm][maxstate],op[maxm][maxstate];
map<vector<int>, int> ID;
vector<vector<int> > state;
void inp(){
if(kase++) cout<<endl;
for(int i=1;i<=n;i++){
cin>>name[i]>>s[i]>>k[i];
for(int j=1;j<=m;j++){
cin>>price[i][j];
price[i][j]*=s[i];
}
}
}
void dfs(int stock,vector<int>& lots,int totlot){
if(stock==n+1){
ID[lots]=state.size();
state.push_back(lots);
return ;
}
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+10);
state.clear();
ID.clear();
dfs(1,lots,0);
for(int s=0;s<state.size();s++){
int tot=0;
for(int i=1;i<=n;i++) tot+=state[s][i];
for(int i=1;i<=n;i++){
buy_next[s][i]=sell_next[s][i]=-1;
if(state[s][i]<k[i]&&tot<kk){
vector<int> newstate=state[s];
newstate[i]++;
buy_next[s][i]=ID[newstate];
}
if(state[s][i]>0){
vector<int> newstate=state[s];
newstate[i]--;
sell_next[s][i]=ID[newstate];
}
}
}
}
void update(int s1,int d2,int s2,double v,int val){
if(v>dp[d2][s2]){
dp[d2][s2]=v;
pre[d2][s2]=s1;
op[d2][s2]=val;
}
}
void work(){
for(int i=0;i<=m+1;i++)
for(int j=0;j<state.size();j++) dp[i][j]=-inf;
dp[1][0]=c;
for(int d=1;d<=m;d++){
for(int s=0;s<state.size();s++){
double v=dp[d][s];
if(v<-1) continue;
update(s,d+1,s,v,0);
for(int i=1;i<=n;i++){
if(buy_next[s][i]>=0&&v>=price[i][d]-1e-3) update(s,d+1,buy_next[s][i],v-price[i][d],i);
if(sell_next[s][i]>=0) update(s,d+1,sell_next[s][i],v+price[i][d],-i);
}
}
}
printf("%.2lf\n",dp[m+1][0]);
}
void print(int day,int st){
if(day==1) return ;
print(day-1,pre[day][st]);
if(op[day][st]>0) cout<<"BUY "<<name[op[day][st]]<<endl;
else if(op[day][st]==0) cout<<"HOLD"<<endl;
else cout<<"SELL "<<name[-op[day][st]]<<endl;
}
int main(){
while(cin>>c>>m>>n>>kk){
inp();
init();
work();
print(m+1,0);
}
return 0;
}