POJ3513 Let's Go to the Movies

  POJ3513 Let's Go to the Movies
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1736 Accepted: 429

Description

A favorite pastime for big families in Acmestan is going to the movies. It is quite common to see a number of these multi-generation families going together to watch a movie. Movie theaters in Acmestan have two types of tickets: A single ticket is for exactly one person while a family ticket allows a parent and their children to enter the theater. Needless to say, a family ticket is always priced higher than a single ticket, sometimes as high as five times the price of a single ticket.

It is quite challenging for families to decide which ticket arrangement is most economical to buy. For example, the family depicted in the figure on the right has four ticket arrangements to choose from: Seven single tickets; Two family tickets; One family ticket (for adam,bobcindy) plus four single tickets for the rest; Or, one family ticket (for bob and his four children) plus single tickets for the remaining two.

Write a program to determine which ticket arrangement has the least price. If there are more than one such arrangement, print the arrangement that has the least number of tickets.

Input

Your program will be tested on one or more test cases. The first line of each test case includes two positive integers (S and F) where S is the price of a single ticket and F is the price of a family ticket. The remaining lines of the test case are either the name of a person going by him/herself, or of the form:

N1 N2 N3 … Nk

where N1 is the name of a parent, with N2… Nk being his/her children. Names are all lower-case letters, and no longer than 1000 characters. No parent will be taking more than 1000 of their children to the movies :-). Names are unique, the name of a particular person will appear at most twice: Once as a parent, and once as a child. There will be at least one person and at most 100,000 people in any test case.

The end of a test case is identified by the beginning of the following test case (a line made of two integers.) The end of the last test case is identified by two zeros.

Output

For each test case, write the result using the following format:

k. NS NF T

Where k is the test case number (starting at 1), NS is the number of single tickets, NF is the number of family tickets, and T is the total cost of tickets.

Sample Input

1 3

adam bob cindy

bob dima edie fairuz gary

1 2

john

paul

george

ringo

1 3

a b c

0 0

Sample Output

1. 2 1 5

2. 4 0 4

3. 0 1 3

Source

******************************************************************************
题目大意:ben1222说这道题是“多细胞看电影”,我笑翻了。题目的意思是,有一户家庭去看电影,看电影可以买家庭票也可以买个人票,个人票的票价总比家庭票的票价低。家庭票只能由父亲或者母亲买,只能带领ta的儿子去看,也就是如果有三代人去看电影,至少要买两张家庭票。现在问怎么买票比较合算,以及如果有多种情况买到最合算的票时,需要票数张数最少的那个组合。
解题思路:第一句话:从来没看见过这么恶心的输入,出题人那个叫大坑爹啊!我还被逼用了sscanf,从来没用过,汗!回归正题。当输入完后就需要把这些个人名离散化,当然用map就够了。离散化后根据直系关系就形成了一棵树,然后就是树形dp。每个节点有两个状态:0是该节点还没被覆盖,即这个根的父亲一定要卖家庭票;1表示这个节点已经买过票了。
#include <stdio.h>

#include <string>

#include <string.h>

#include <iostream>

#include <vector>

#include <map>

#define N 100005

using namespace std;



vector<long long>gra[N];

map<string,long long>hash;

string nam;

char str[1000*2000+5];

long long s,f,vis[N],id;

struct Dp

{

    long long ns,nf;

}dp[N][2];



void dfs(long long r)

{

    vis[r]=1;

    Dp temp;

    dp[r][1].nf=1;

    for(long long i=0;i<gra[r].size();i++)

    {

        long long t=gra[r][i];

        dfs(t);

        long long a=s*dp[t][0].ns+f*dp[t][0].nf;

        long long b=s*dp[t][1].ns+f*dp[t][1].nf;

        if(a>b||(a==b&&dp[t][1].nf>dp[t][0].nf))

        {

            dp[r][1].ns+=dp[t][1].ns;

            dp[r][1].nf+=dp[t][1].nf;

        }

        else

        {

            dp[r][1].ns+=dp[t][0].ns;

            dp[r][1].nf+=dp[t][0].nf;

        }

        dp[r][0].ns+=dp[t][1].ns;

        dp[r][0].nf+=dp[t][1].nf;

    }

    long long a=s*dp[r][0].ns+s+f*dp[r][0].nf;

    long long b=s*dp[r][1].ns+f*dp[r][1].nf;

    if(a<b||(a==b&&dp[r][0].nf>dp[r][1].nf))

    {

        dp[r][1].ns=dp[r][0].ns+1;

        dp[r][1].nf=dp[r][0].nf;

    }



}



void run(long long h)

{

    Dp ans;

    ans.nf=ans.ns=0;

    for(long long i=1;i<id;i++)

        if(vis[i]==0)

        {

            dfs(i);

            ans.nf+=dp[i][1].nf;

            ans.ns+=dp[i][1].ns;

        }

    printf("%lld. %lld %lld %lld\n",h,ans.ns,ans.nf,s*ans.ns+f*ans.nf);

}



int main()

{

    gets(str);

    for(long long h=1;;h++)

    {

        sscanf(str,"%lld%lld",&s,&f);

        if(s==0&f==0)break;

        id=1;

        for(long long i=0;i<N;i++)

            gra[i].clear();

        hash.clear();

        memset(dp,0,sizeof(dp));

        memset(vis,0,sizeof(vis));

        while(1)

        {

            gets(str);

            if(str[0]>='0'&&str[0]<='9')break;

            if(!(str[0]>='a'&&str[0]<='z'))continue;

            long long flag=0,k=0,len=strlen(str),fa;

            char temp[1005];

            for(long long i=0;i<=len;i++)

            {

                if(i==len||str[i]==' ')

                {

                    temp[k]=0;

                    k=0;

                    nam=temp;

                    if(hash.count(nam)==0)hash[nam]=id++;

                    if(flag==0)

                        flag=1,fa=hash[nam];

                    else

                        gra[fa].push_back(hash[nam]),vis[hash[nam]]=1;

                    continue;

                }

                temp[k++]=str[i];

            }

        }

        run(h);

    }

}

  

你可能感兴趣的:(poj)