UVALive 4048 Fund Management

题目大意:你有c美元,没有股票,给你m天时间和n支股票供你买卖,每天只能买卖一手股票,对于第i支股票,知道他的第j天的每股价格为Pij,一手为si股,且每天最多能持有ki手这支股票,且所持股票的总手数不能超过k,问你m天后最多能得到的钱(最后一天结束时不能持有任何股票),并打印路径。

思路:一看数据范围,很容易想到是状压。我的思路是开d[ i ][ j ] 表示前i天手上每支股票的手数为j,则 j 相当为 9 进制表示的数,用来表示各自数量。用 map 来存 d 数组,再记忆化搜索,状态转移时注意判断条件是否满足。

哎,搞了一个下午,一直WA,写博客的心情都没了,TLE么,那就算了。。 T^T

先贴个WA的代码,挖个坑,以后再来填吧。。 希望各位路过的大神能不吝赐教。。 T^T

代码如下(WA ):

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;

#define MP make_pair

typedef __int64 lld;

const lld INF = 1e15;

const double EPS = 0.005;

struct Stock
{
    char name[11];
    int len,k;
    lld pri[111];
} stock[11];

map <int,lld> d[111];
map <int,int> vis[111];

int m,n;

int k;

int count(int s)
{
    int cnt = 0;
    for(int i = 0;i<n;i++)
    {
        cnt += s%9;
        s = s/9;
    }
    return cnt;
}

lld exp[11];

void init()
{
    exp[0] = 1;
    for(int i = 1;i<8;i++)
    {
        exp[i] = exp[i-1] * 9;
    }
}

map <int , pair<int,int> > path[111];

lld dp(int day,int s,lld c)
{
    if(vis[day][s]) return d[day][s];
    vis[day][s] = 1;
    lld &ans = d[day][s];
    if(day >= m )
    {
        if(s == 0) return ans = 0;
        else return ans = -INF;
    }
    ans = -INF;
    int cc = count(s);
    //printf("day = %d,s = %d,cc = %d\n",day,s,cc);
    if(cc<k)
    {
        int tmp = s;
        for(int i = 0;i<n;i++)
        {
            if(tmp%9<stock[i].k)
            {
                if(c >= stock[i].pri[day] && dp(day+1,s + exp[i], c - stock[i].pri[day]) - stock[i].pri[day] > ans)
                {
                    ans = dp(day+1,s + exp[i],c - stock[i].pri[day]) - stock[i].pri[day];
                    path[day][s] = MP(0,i);
                    path[day][s] = MP(0,i);
                }
            }
            tmp /= 9;
        }
    }
    int tmp = s;
    for(int i = 0;i<n;i++)
    {
        if(tmp%9>0)
        {
            if(dp(day+1,s - exp[i] , c + stock[i].pri[day]) + stock[i].pri[day] > ans)
            {
                ans = dp(day+1,s - exp[i], c + stock[i].pri[day]) + stock[i].pri[day];
                path[day][s] = MP(1,i);
            }
        }
        tmp /= 9;
    }
    if(dp(day+1,s,c) > ans)
    {
        ans = dp(day+1,s,c);
        path[day][s] = MP(-1,-1);
    }
    //printf("day = %d,s = %d,ans = %I64d\n",day,s,ans);
    return ans;
}

void print(int day,int s)
{
    if(day>=m) return ;
    int to;
    if(path[day][s].first == 0 )
    {
        printf("BUY %s\n",stock[path[day][s].second].name);
        to = s + exp[path[day][s].second];
    }
    else if(path[day][s].first == 1)
    {
        printf("SELL %s\n",stock[path[day][s].second].name);
        to = s - exp[path[day][s].second];
    }
    else
    {
        puts("HOLD");
        to = s;
    }
    print(day+1,to);
}

int main()
{
    init();
    double tmp;
    while(~scanf("%lf%d%d%d",&tmp,&m,&n,&k))
    {
        lld c = (lld)((tmp+EPS)*100);
        for(int i = 0;i<n;i++)
        {
            scanf("%s%d%d",stock[i].name,&stock[i].len,&stock[i].k);
            for(int j = 0;j<m;j++)
            {
                scanf("%lf",&tmp);
                stock[i].pri[j] = (lld)((tmp+EPS)*100)*stock[i].len;
                printf("%I64d\n",stock[i].pri[j]);
            }
        }
        for(int i = 0;i<=m;i++)
        {
            d[i].clear();
            vis[i].clear();
            path[i].clear();
        }
        printf("%.2lf\n",(double)((c + dp(0,0,c))/100.0));
        print(0,0);
    }
    return 0;
}

/*
144624.00 9 5 3
IBM 500 3
97.27 98.31 97.42 98.9 100.07 98.89 98.65 99.34 100.82
GOOG 100 1
467.59 483.26 487.19 483.58 485.5 489.46 499.72 505 504.28
JAVA 1000 2
5.54 5.69 5.6 5.65 5.73 6 6.14 6.06 6.06
MSFT 250 1
29.86 29.81 29.64 29.93 29.96 29.66 30.7 31.21 31.16
ORCL 300 3
17.51 17.68 17.64 17.86 17.82 17.77 17.39 17.5 17.3

144624.00 2 1 1
IBM 500 3
97.27 98.31

100 1 1 1
A 1 1
100

*/

再来个java的AC代码,乱搜搜来的,没仔细看,也懒得看,先贴上:

import java.io.*;
import java.util.*;

public class Main {
    static Scanner in;
    static PrintWriter out;

    long c;
    int m;
    int n;
    int k;

    class Stock {
        String name;
        int count;
        long[] price = new long[m];

        Stock(Scanner in) {
            name = in.next();
            long size = in.nextInt();
            count = in.nextInt();

            for (int i = 0; i < m; i++) {
                price[i] = Math.round(in.nextDouble() * 100) * size;
            }
        }
    }

    Stock[] stocks;

    List<Transition[]> transitions = new ArrayList<Transition[]>();
    Map<Integer, Integer> codes = new HashMap<Integer, Integer>();
    int lastCode = 0;

    int encode(int[] count) {
        int q = 0;
        for (int i = 0; i < n; i++) {
            q = q * (k + 1) + count[i];
        }
        if (!codes.containsKey(q)) {
            codes.put(q, lastCode++);
        }
        return codes.get(q);
    }

    class Transition {
        final int from;
        final int to;
        final int buy;
        final int sell;

        Transition(int from, int to, int buy, int sell) {
            this.from = from;
            this.to = to;
            this.buy = buy;
            this.sell = sell;
        }

        long cost(int day) {
            return 
                ((buy >= 0) ? stocks[buy].price[day] : 0) + 
                ((sell >= 0) ? -stocks[sell].price[day] : 0);
        }

        @Override
        public String toString() {
            if (buy >= 0) return "BUY " + stocks[buy].name;
            if (sell >= 0) return "SELL " + stocks[sell].name;
            return "HOLD";
        }
    }

    int generate(int[] count, int c) {
        int code = encode(count);
        if (transitions.size() == code) {
            List<Transition> transitions = new ArrayList<Transition>();
            this.transitions.add(null);

            transitions.add(new Transition(code, code, -1, -1));
            
            for (int i = 0; i < n; i++) {
                if (count[i] < stocks[i].count && c < k) {
                    count[i]++;
                    transitions.add(new Transition(code, generate(count, c + 1), i, -1));
                    count[i]--;
                }
                if (count[i] > 0) {
                    count[i]--;
                    transitions.add(new Transition(code, generate(count, c - 1), -1, i));
                    count[i]++;
                }
            }
            this.transitions.set(code, transitions.toArray(new Transition[transitions.size()]));
            //System.out.println(Arrays.toString(count) + " " + transitions.size());
        }
        return code;
    }

    long[][] max;

    void run() {
        c = Math.round(in.nextDouble() * 100);
        m = in.nextInt();
        n = in.nextInt();
        k = in.nextInt();

        stocks = new Stock[n];
        for (int i = 0; i < n; i++) {
            stocks[i] = new Stock(in);
        }

        int root = generate(new int[n], 0);

        max = new long[m + 1][lastCode];
        Arrays.fill(max[0], -1);
        max[0][root] = c;

        Transition[][] by = new Transition[m + 1][lastCode];

        //System.out.println(lastCode);

        for (int i = 0; i < m; i++) {
            long[] current = max[i];
            long[] next = max[i + 1];
            Arrays.fill(next, -1);
            for (int j = 0; j < lastCode; j++) {
                if (current[j] >= 0) {
                    for (Transition transition : transitions.get(j)) {
                        int to = transition.to;
                        long cost = current[j] - transition.cost(i);
                        if (next[to] < cost) {
                            next[to] = cost;
                            by[i + 1][to] = transition;
                        }
                    }
                }
            }                              
        }
        System.out.format("%.2f\n", max[m][root] / 100.0);
        List<Transition> actions = new LinkedList<Transition>();
        int j = root;
        for (int i = m; i > 0; i--) {
            actions.add(0, by[i][j]);
            j = by[i][j].from;
        }
        for (Transition t : actions) {
            System.out.println(t);
        }
    }

    public static void main(String[] args) throws IOException {
        //Locale.setDefault(Locale.US);
        in = new Scanner(System.in);
        //out = new Scanner(System.out);

//        while (in.hasNext()) {
            new Main().run();
//        }

        //out.close();
        //in.close();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值