题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=3513

题目大意是输入树状的家庭关系,问怎么买票(买家庭票还是个人票)最省钱并且票的数量最少

这道题是一道Hash+树状DP问题。编码长度相当可观,需要较好的编码能力

我这题编码就犯了几个低级错误,然后算法错误一次,导致了无数的WA

先给几组测试数据

2 3
a b
b c
c d
2 3
a b c
b d e
c f g
d h i
e j k
f l m
g n o
1 3
a b c d e
f g h i j a n k l
n m o p q
0 0

答案是:

1. 0 2 6

2. 0 5 15

3. 0 3 9

贴代码(注意下代码是C++的。由于使用了 cin和cout,G++有输入优化会降低cin和cout的时间,如果用G++要把cin和cout改成scanf和printf,然后少用string,否则会TLE):

/**
* Author: OWenT
* POJ PKU 3513 Let's Go to the Movies
* http://acm.pku.edu.cn/JudgeOnline/problem?id=3513
* 树形DP + Hash
* WA了好多次
*/

#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;

#define MAXN 100005
typedef struct
{
    vector<long>chirldren;
    bool isPF;
    long m_t,m_s,m_f;
    char tt;
}node;
node glo[MAXN];
map<string, long>hash;
long nodeNum;

void check(long pos, long &ns, long &nf, long &t, long &s, long &f);
void checkChirld(long pos, long &ns, long &nf, long &t, long &s, long &f);
void initNode(long &pos);
int main()
{
    //freopen("d:\\movies.in.txt","r",stdin);
    //freopen("d:\\movies.out.txt","w",stdout);
    long s,f, k = 0;
    long ns,nf,t;
    long tmpPos1,tmpPos2, i;
    string str;
    while(cin>> str)
    {
        if(str[0] <= '9' && str[0] >= '0')
        {
            //处理数据
            if(k)
            {
                for(i = 0; i < nodeNum; i ++)
                    if(glo[i].isPF)
                        check(i, ns, nf, t, s, f);
                //输出
                printf("%ld. %ld %ld %ld\n", k, ns, nf, t);
            }

            //下一组数据
            k ++;
            ns = nf = t = nodeNum = 0;
            cin>> f;
            s = atol(str.c_str());
            if(!s && !f)
                break;
            hash.clear();
        }
        else
        {
            //父节点映射
            if(hash.find(str) == hash.end())
            {
                initNode(nodeNum);
                hash[str] = nodeNum;
                tmpPos1 = nodeNum ++;
            }
            else
                tmpPos1 = hash[str];
            //子节点映射
            while(getchar() != '\n')
            {
                cin>> str;
                if(hash.find(str) == hash.end())
                {
                    initNode(nodeNum);
                    hash[str] = nodeNum;
                    tmpPos2 = nodeNum ++;
                }
                else
                    tmpPos2 = hash[str];
                glo[tmpPos1].chirldren.push_back(tmpPos2);
                glo[tmpPos2].isPF = false;
            }
        }
    }
    return 0;
}

void check(long pos, long &ns, long &nf, long &t, long &s, long &f)
{
    //0为当前个人票数据,1为当前家庭票数据
    long tns[2] = {1, 0},
        tnf[2] = {0, 1},
        tt[2] = {s, f};
    long i, n = 0;
    if(glo[pos].m_t >= 0)
    {
        ns += glo[pos].m_s;
        nf += glo[pos].m_f;
        t += glo[pos].m_t;
        return;
    }
    for(i = 0; i < glo[pos].chirldren.size(); i ++)
        check(glo[pos].chirldren[i], tns[0], tnf[0], tt[0], s, f);//当前个人票的结果
    checkChirld(pos, tns[1], tnf[1], tt[1], s, f);//当前家庭票的结果
    if(tt[0] < tt[1] || (tt[0] == tt[1] && tns[0] + tnf[0] <= tns[1] + tnf[1]))
    {
        t += tt[0];
        ns += tns[0];
        nf += tnf[0];
        glo[pos].m_f = tnf[0];
        glo[pos].m_s = tns[0];
        glo[pos].m_t = tt[0];
        glo[pos].tt = 's';
    }
    else
    {
        t += tt[1];
        ns += tns[1];
        nf += tnf[1];
        glo[pos].m_f = tnf[1];
        glo[pos].m_s = tns[1];
        glo[pos].m_t = tt[1];
        glo[pos].tt = 'f';
    }
    //printf("ID:%ld: f:%ld s:%ld t:%ld TicketType: %c\n", pos, glo[pos].m_f, glo[pos].m_s, glo[pos].m_t, glo[pos].tt);
}
void initNode(long &pos)
{
    glo[pos].isPF = true;
    glo[pos].chirldren.clear();
    glo[pos].m_f = glo[pos].m_s = glo[pos].m_t = -1;
}

void checkChirld(long pos, long &ns, long &nf, long &t, long &s, long &f)
{
    long i, j, k, l;
    long len1, len2;
    long tns[2],tnf[2],tt[2];
    len1 = glo[pos].chirldren.size();
    for(i = 0; i < len1; i ++)
    {
        k = glo[pos].chirldren[i];
        tns[0] = glo[ k ].m_s;
        tnf[0] = glo[ k ].m_f;
        tt[0] = glo[ k ].m_t;
        tns[1] = 0;
        tnf[1] = 0;
        tt[1] = 0;
        len2 = glo[ k ].chirldren.size();
        for(j = 0; j < len2; j ++)
        {
            l = glo[k].chirldren[j];
            check(l, tns[1], tnf[1], tt[1], s, f);
        }
        if(tt[0] < tt[1] || (tt[0] == tt[1] && tns[0] + tnf[0] <= tns[1] + tnf[1]))
        {
            t += tt[0];
            ns += tns[0];
            nf += tnf[0];
        }
        else
        {
            t += tt[1];
            ns += tns[1];
            nf += tnf[1];
        }
    }
}