UVA 1412 Fund Management (预处理+状压dp)

状压dp,每个状态可以表示为一个n元组,且上限为8,可以用一个九进制来表示状态。但是这样做用数组开不下,用map离散会T。

而实际上很多九进制数很多都是用不上的。因此类似uva 1601 Morning after holloween的思想,先dfs预处理出所有状态,用map将状态离散,

预处理出算出状态的转移DAG,而不是转移的时候在解码编码判断是否可行,然后一层一层bfs就行了。

附上测试数据

一层一层的bfs转移类似滚动数组,注意初始化(具体问题具体分析,有些问题没有必要做这一步)

一层一层的bfs,0.293s

#include<bits/stdc++.h>
using namespace std;
const int maxn = 8, maxm = 105;
double c;
int m,n,K;

const int maxlen = 10;
char names[maxn][maxlen];

int k[maxn];
double price[maxn][maxm];


typedef vector<int> State;
vector<State> states;
#define PB push_back

map<State,int> ID;
map<State,int>:: iterator it;
#define MP make_pair
#define fi first
#define se second

const int maxst = 13000;

State st;
void GetAllSta(int i)
{
    if(i == n){
        ID.insert(MP(st,states.size()));
        states.PB(st);
        return;
    }
    for(int j = 0; j <= k[i] && st[n]+j <= K; j++){
        st[i] = j;
        st[n]+=j;
        GetAllSta(i+1);
        st[n]-=j;
    }
}


int buy[maxst][maxn],sell[maxst][maxn];


void buildDAG()
{
    st.resize(n+1);
    if(states.size()) states.clear();
    ID.clear();
    GetAllSta(0);
    for(int s = 0; s < states.size(); s++){
        State &cur = states[s];
        for(int i = 0; i < n; i++){
            buy[s][i] = sell[s][i] = -1;
            if(cur[i] < k[i] && cur[n] <K){
                cur[i]++; cur[n]++;
                buy[s][i] = ID[cur];
                cur[i]--; cur[n]--;
            }
            if(cur[i]>0){
                cur[i]--; cur[n]--;
                sell[s][i] = ID[cur];
                cur[i]++; cur[n]++;
            }
        }
    }
}

double dp[2][maxst];
int pre[maxm-4][maxst];
int opt[maxm-4][maxst];

void updata(int u,int v,double money,double *nxt,int day,int op,vector<int>* tomorrow)
{
     if(nxt[v]  < money ){
        if(nxt[v] < -1.0){
            tomorrow->PB(v);
        }
        opt[day][v] = op;
        pre[day][v] = u;
        nxt[v] = money;

    }
}

vector<int> V1,V2;
void bfs()
{
    V1.clear(); V2.clear();
    int sz = states.size();
    fill(dp[0],dp[0]+sz+1,-666);
    vector<int>* today = &V1, *tomorrow = &V2;
    today->PB(0); dp[0][0] = c;
    for(int day = 0; day < m; day++){
        double *const&cur = dp[day&1], *const&nxt = dp[day&1^1];
        fill(nxt,nxt+sz+1,-666);
        int tsz = today->size();
        for(int j = 0; j < tsz; j++){
            int s = (*today)[j];
            double money = cur[s];
            updata(s,s,money,nxt,day,0,tomorrow);
            for(int i = 0; i < n; i++){
                double stockPrice = price[i][day];
                if(sell[s][i] >= 0){
                    updata(s,sell[s][i],money+stockPrice,nxt,day,-i-1,tomorrow);
                }
                if(buy[s][i] >= 0 && money >= price[i][day] ){
                    updata(s,buy[s][i],money-stockPrice,nxt,day,i+1,tomorrow);
                }
            }
        }
        swap(today,tomorrow);
        tomorrow->clear();
    }
}


void read()
{
    for(int i = 0; i < n; i++){
        int s; scanf("%s%d%d",names[i],&s,k+i);
        for(int j = 0; j < m; j++){
            scanf("%lf",price[i]+j);
             price[i][j] *= s;
        }
    }
}


void print_ans()
{
    int ans[maxm], u = 0;
    printf("%lf
",max(dp[m&1][u],dp[m&1^1][u]));
    for(int i = m-1; i >= 0; i--){
        ans[i] = opt[i][u];
        u = pre[i][u];
    }
    for(int i = 0; i < m; i++){
        int t = ans[i];
        if(t){
            if(t>0) printf("BUY %s
",names[t-1]);
            else printf("SELL %s
",names[-t-1]);
        }else puts("HOLD");
    }

}

int main()
{
    //freopen("in.txt","r",stdin);
    while(~scanf("%lf%d%d%d",&c,&m,&n,&K)){
        read();
        buildDAG();
        bfs();
        print_ans();
    }
    return 0;
}
View Code

直接按时间dp,0.199s

#include<bits/stdc++.h>
using namespace std;
const int maxn = 8, maxm = 105;
double c;
int m,n,K;

const int maxlen = 10;
char names[maxn][maxlen];

int k[maxn];
double price[maxn][maxm];



typedef vector<int> State;
vector<State> states;
#define PB push_back


map<State,int> ID;
map<State,int>:: iterator it;
#define MP make_pair
#define fi first
#define se second

const int maxst = 13000;

State st;
void GetAllSta(int i)
{
    if(i == n){
        ID.insert(MP(st,states.size()));
        states.PB(st);
        return;
    }
    for(int j = 0; j <= k[i] && st[n]+j <= K; j++){
        st[i] = j;
        st[n] += j;
        GetAllSta(i+1);
        st[n] -= j;
    }
}


int buy[maxst][maxn],sell[maxst][maxn];


void buildDAG()
{
    st.resize(n+1);
    states.clear();
    ID.clear();
    GetAllSta(0);
    for(int s = 0; s < states.size(); s++){
        State &cur = states[s];
        for(int i = 0; i < n; i++){
            buy[s][i] = sell[s][i] = -1;
            if(cur[i] < k[i] && cur[n] < K){
                cur[i]++; cur[n]++;
                buy[s][i] = ID[cur];
                cur[i]--; cur[n]--;
            }
            if(cur[i]>0){
                cur[i]--; cur[n]--;
                sell[s][i] = ID[cur];
                cur[i]++; cur[n]++;
            }
        }
    }
}

double d[2][maxst];
int pre[maxm-4][maxst];
int opt[maxm-4][maxst];

void updata(int u,int v,double money,double *nxt,int day,int op)
{
    if(nxt[v] < money){
        nxt[v] = money;
        opt[day][v] = op;
        pre[day][v] = u;
    }
}

void dp()
{
    int sz = states.size();
    fill(d[0],d[0]+sz+1,-666);
    d[0][0] = c;
    for(int day = 0; day < m; day++){
        double *today = d[day&1], (&tomorrow)[maxst] = d[(day&1)^1];
        fill(tomorrow,tomorrow+sz+1,-233);
        for(int s = 0; s < sz; s++) {
            double mon = today[s];
            if(mon < -1) continue;
            updata(s,s,mon,tomorrow,day,0);
            for(int i = 0; i < n; i++){
                double val = price[i][day];
                if(buy[s][i] >= 0 && mon >= val){
                    updata(s,buy[s][i],mon-val,tomorrow,day,i+1);
                }
                if(sell[s][i] >= 0){
                    updata(s,sell[s][i],mon+val,tomorrow,day,-i-1);
                }
            }
        }
    }
}


void read()
{
    for(int i = 0; i < n; i++){
        int s; scanf("%s%d%d",names[i],&s,k+i);
        for(int j = 0; j < m; j++) {
            scanf("%lf",price[i]+j);
             price[i][j] *= s;
        }
    }
}


void print_ans()
{
    int ans[maxm], u = 0;
    printf("%lf
",d[m&1][0]);
    for(int i = m-1; i >= 0; i--){
        ans[i] = opt[i][u];
        u = pre[i][u];
    }
    for(int i = 0; i < m; i++){
        int t = ans[i];
        if(t){
            if(t>0) printf("BUY %s
",names[t-1]);
            else printf("SELL %s
",names[-t-1]);
        } else puts("HOLD");
    }

}

int main()
{
    //freopen("in.txt","r",stdin);
    while(~scanf("%lf%d%d%d",&c,&m,&n,&K)){
        read();
        buildDAG();
        dp();
        print_ans();
    }
    return 0;
}
View Code

附上1组测试数据

8765.43 100 8 8
EKXOU 8 8
497.60 572.49 777.30 798.74 856.42 907.12 951.80 973.32 997.39 428.54 285.77 21.88 15.36 11.55 6.48 5.64 4.73 0.35 0.10 511.06 825.53 961.92 962.12 989.97 994.93 996.52 997.17 999.80 999.87 124.40 60.90 27.93 16.15 1.18 0.49 0.08 0.01 0.01 0.01 482.35 502.45 689.55 894.80 943.09 968.54 978.27 981.05 990.68 998.48 180.68 51.73 10.82 1.58 1.41 1.35 1.00 0.91 0.09 0.07 264.18 389.68 861.28 924.38 930.49 987.65 994.23 994.57 997.81 998.38 0.09 0.04 0.03 0.03 0.02 0.02 0.02 0.01 0.01 0.01 764.88 784.31 881.75 979.84 995.53 995.88 999.45 999.50 999.50 999.88 51.96 41.72 0.31 0.08 0.02 0.02 0.02 0.02 0.01 0.01 783.83
TOJIX 4 7
337.36 798.61 959.78 974.23 974.66 980.52 985.75 988.00 997.75 202.70 22.45 9.80 9.75 1.37 1.25 0.08 0.07 0.01 0.01 453.79 956.23 974.28 975.82 984.13 997.62 998.44 999.34 999.55 999.70 720.60 279.71 263.45 125.87 19.68 2.05 0.34 0.19 0.18 0.09 956.28 983.92 998.93 999.21 999.49 999.94 999.95 999.97 999.98 999.99 420.16 201.90 171.95 105.75 55.79 5.57 2.35 0.29 0.26 0.07 287.31 833.57 923.40 973.86 989.51 996.69 998.67 999.51 999.76 999.96 592.20 253.01 135.07 47.59 36.20 20.77 4.27 2.15 2.08 0.41 824.65 844.61 914.04 946.35 986.53 993.71 998.21 999.08 999.74 999.81 31.97 6.57 0.89 0.87 0.28 0.06 0.06 0.06 0.04 0.02 543.05
YPBR 1 4
261.13 726.56 902.28 968.30 986.36 990.99 992.91 997.18 998.05 620.09 544.18 109.24 105.36 102.12 92.24 71.58 11.44 10.93 10.48 949.78 979.18 999.29 999.73 999.94 999.97 999.99 999.99 999.99 999.99 303.75 32.27 19.46 3.00 0.68 0.57 0.07 0.05 0.05 0.05 847.31 875.92 878.64 948.43 950.97 962.84 998.62 999.77 999.83 999.91 792.80 732.09 518.26 300.41 266.92 254.44 120.94 97.95 50.42 0.22 949.73 955.52 960.78 969.87 989.54 990.62 997.12 998.91 998.92 999.95 435.46 244.96 105.08 83.05 71.16 57.48 0.35 0.26 0.04 0.03 672.62 674.93 994.14 998.04 999.76 999.95 999.98 999.99 999.99 999.99 890.88 587.16 522.23 198.58 48.06 43.10 8.27 8.16 2.78 2.09 654.25
DMQHU 3 5
786.12 989.55 998.11 998.79 999.06 999.51 999.99 999.99 999.99 329.96 234.31 213.10 50.98 25.55 9.33 6.15 4.62 3.76 1.45 473.40 861.35 891.83 893.32 994.48 994.82 995.74 997.51 999.60 999.61 1.60 0.10 0.04 0.03 0.02 0.02 0.02 0.01 0.01 0.01 955.63 962.79 991.17 997.12 997.78 999.24 999.52 999.56 999.90 999.97 248.19 21.63 17.23 0.77 0.15 0.02 0.01 0.01 0.01 0.01 645.78 794.76 945.82 951.66 957.98 969.25 979.61 983.05 999.01 999.98 142.88 48.33 6.78 1.40 0.30 0.11 0.01 0.01 0.01 0.01 455.03 961.87 971.42 993.53 994.89 999.22 999.40 999.49 999.97 999.98 572.16 101.80 11.67 5.90 3.43 0.95 0.52 0.35 0.02 0.01 30.77
PA 4 5
171.57 814.60 880.12 930.74 999.37 999.85 999.94 999.95 999.99 616.08 337.98 275.98 268.51 144.13 73.64 9.64 5.77 3.64 1.16 635.71 887.63 942.64 973.01 988.12 988.27 997.58 998.96 999.49 999.63 595.22 61.20 54.08 45.03 30.42 15.34 1.37 1.13 0.27 0.13 315.10 713.86 918.35 924.16 934.51 946.22 986.08 991.68 997.52 997.85 910.50 385.99 38.53 23.88 9.77 4.83 1.56 1.12 1.08 0.59 798.72 925.88 991.50 994.57 999.42 999.45 999.74 999.96 999.96 999.98 409.21 306.84 13.02 5.35 1.71 1.09 0.05 0.05 0.01 0.01 461.25 580.76 659.42 820.34 934.58 979.96 983.33 993.69 995.64 996.48 217.36 102.03 55.09 1.02 0.07 0.04 0.03 0.01 0.01 0.01 756.52
GDXR 5 5
315.11 980.66 994.48 996.51 999.23 999.27 999.43 999.98 999.98 474.90 467.57 332.03 259.91 237.15 201.72 7.17 2.86 2.86 1.84 650.61 751.90 770.80 893.72 969.27 980.07 992.74 999.52 999.70 999.89 990.81 893.66 304.11 283.43 159.01 25.83 18.51 5.64 2.78 0.61 753.95 879.59 931.70 952.85 960.27 984.89 997.82 999.81 999.84 999.86 31.61 22.43 8.18 6.64 6.01 1.96 0.82 0.33 0.30 0.22 476.24 680.51 737.71 958.51 962.28 999.90 999.90 999.95 999.97 999.99 817.03 80.43 35.66 0.16 0.08 0.04 0.01 0.01 0.01 0.01 639.87 907.28 966.39 991.41 994.12 999.86 999.94 999.98 999.98 999.99 790.20 95.68 26.30 11.24 3.25 2.46 2.38 0.94 0.41 0.35 46.40
EHCN 10 2
36.99 751.66 794.23 984.85 991.56 995.68 995.84 998.77 999.24 362.81 331.16 56.41 47.53 3.28 3.26 2.10 0.46 0.05 0.04 426.68 789.10 883.32 972.42 982.25 992.18 999.99 999.99 999.99 999.99 861.04 780.38 1.12 0.05 0.05 0.01 0.01 0.01 0.01 0.01 822.44 874.05 974.89 978.78 999.96 999.96 999.98 999.99 999.99 999.99 237.58 43.68 32.98 19.61 7.45 2.53 1.39 0.88 0.65 0.23 55.26 638.65 727.28 832.58 995.85 999.88 999.95 999.95 999.99 999.99 447.03 329.97 247.45 31.78 1.85 1.56 1.38 1.29 1.21 1.14 863.62 954.56 981.69 982.01 986.16 991.74 998.82 999.49 999.52 999.54 586.70 151.55 104.38 71.89 5.38 2.25 0.78 0.48 0.19 0.06 11.43
LSEDH 5 1
678.83 957.20 975.00 999.45 999.97 999.98 999.98 999.98 999.98 785.99 712.30 476.84 87.14 36.88 25.14 10.90 1.70 1.04 0.04 799.70 983.34 992.55 993.58 994.11 994.86 996.95 998.88 999.82 999.85 759.48 560.12 180.82 61.18 40.45 10.25 6.36 5.09 3.91 1.43 955.45 993.56 993.96 999.00 999.69 999.88 999.90 999.96 999.98 999.99 165.77 144.71 54.31 40.19 27.33 26.45 3.48 0.85 0.29 0.16 119.74 760.63 976.18 987.90 996.92 999.90 999.95 999.96 999.96 999.98 357.32 175.40 7.05 2.21 1.42 0.82 0.57 0.07 0.07 0.01 648.07 833.15 972.96 993.92 996.42 999.70 999.75 999.75 999.79 999.92 917.38 168.10 152.48 61.59 33.33 19.03 10.88 2.79 2.65 2.23 509.18
View Code

测试数据的答案

298113.06
BUY EHCN
BUY EKXOU
BUY PA
SELL EHCN
BUY EKXOU
HOLD
SELL PA
SELL EKXOU
SELL EKXOU
HOLD
HOLD
BUY EKXOU
BUY EKXOU
BUY EHCN
BUY EKXOU
BUY EKXOU
BUY EHCN
BUY EKXOU
BUY EKXOU
HOLD
SELL EKXOU
BUY GDXR
SELL EHCN
SELL EKXOU
SELL EKXOU
SELL EHCN
SELL EKXOU
SELL EKXOU
SELL EKXOU
SELL GDXR
HOLD
BUY EHCN
BUY EHCN
BUY EKXOU
BUY EKXOU
BUY EKXOU
BUY EKXOU
BUY EKXOU
BUY EKXOU
SELL EHCN
BUY EKXOU
SELL EHCN
SELL EKXOU
SELL EKXOU
SELL EKXOU
SELL EKXOU
SELL EKXOU
SELL EKXOU
SELL EKXOU
HOLD
HOLD
BUY EKXOU
BUY EKXOU
BUY EKXOU
BUY EKXOU
BUY PA
BUY EHCN
BUY EKXOU
BUY EHCN
SELL PA
BUY EKXOU
SELL EKXOU
SELL EKXOU
SELL EHCN
SELL EHCN
SELL EKXOU
SELL EKXOU
SELL EKXOU
SELL EKXOU
HOLD
HOLD
BUY EKXOU
BUY EKXOU
BUY EKXOU
BUY EKXOU
BUY EKXOU
BUY EKXOU
BUY EHCN
BUY EHCN
SELL EHCN
BUY EKXOU
SELL EHCN
SELL EKXOU
SELL EKXOU
SELL EKXOU
SELL EKXOU
SELL EKXOU
SELL EKXOU
SELL EKXOU
HOLD
HOLD
HOLD
HOLD
HOLD
HOLD
HOLD
HOLD
HOLD
BUY EKXOU
SELL EKXOU
View Code

一开始想用dfs+回溯,T了,意识到dfs的话没有用到最优子结构的性质,用九进制+map离散保存状态dp,又T了,

改成预处理出DAG,然后bfs终于过了。

原文地址:https://www.cnblogs.com/jerryRey/p/4750865.html