青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Google code jam 2008 QR - Saving the Universe

Problem

The urban legend goes that if you go to the Google homepage and search for "Google", the universe will implode. We have a secret to share... It is true! Please don't try it, or tell anyone. All right, maybe not. We are just kidding.

The same is not true for a universe far far away. In that universe, if you search on any search engine for that search engine's name, the universe does implode!

To combat this, people came up with an interesting solution. All queries are pooled together. They are passed to a central system that decides which query goes to which search engine. The central system sends a series of queries to one search engine, and can switch to another at any time. Queries must be processed in the order they're received. The central system must never send a query to a search engine whose name matches the query. In order to reduce costs, the number of switches should be minimized.

Your task is to tell us how many times the central system will have to switch between search engines, assuming that we program it optimally.

Input

The first line of the input file contains the number of cases, N. N test cases follow.

Each case starts with the number S -- the number of search engines. The next S lines each contain the name of a search engine. Each search engine name is no more than one hundred characters long and contains only uppercase letters, lowercase letters, spaces, and numbers. There will not be two search engines with the same name.

The following line contains a number Q -- the number of incoming queries. The next Q lines will each contain a query. Each query will be the name of a search engine in the case.

Output

For each input case, you should output:

Case #X: Y
where X is the number of the test case and Y is the number of search engine switches. Do not count the initial choice of a search engine as a switch.

 

Limits

0 < N ≤ 20

Small dataset

2 ≤ S ≤ 10

0 ≤ Q ≤ 100

Large dataset

2 ≤ S ≤ 100

0 ≤ Q ≤ 1000

Sample


Input

Output
2
5
Yeehaw
NSM
Dont Ask
B9
Googol
10
Yeehaw
Yeehaw
Googol
B9
Googol
NSM
B9
NSM
Dont Ask
Googol
5
Yeehaw
NSM
Dont Ask
B9
Googol
7
Googol
Dont Ask
NSM
NSM
Yeehaw
Yeehaw
Googol

Case #1: 1
Case #2: 0

In the first case, one possible solution is to start by using Dont Ask, and switch to NSM after query number 8.
For the second case, you can use B9, and not need to make any switches.


Analysis

The first task in the new Google Code Jam is about, no surprise, search engines, and also, the grandiose feat of saving the universe in a parsimonious way. However, putting all the fancies aside, the problem itself is easy.

List all queries one by one, and break them up into segments. Each segment will be an interval where we use one search engine, and when we cross from one segment to another we will switch the search engine we use. What can you say about each segment? Well, one thing for sure is:

Never ever ever have all S different search engines appear as queries in one segment. (*)
Why is this? Because if all S names appeared in one segment, then any search engine used for that segment will encounter at least one query that is the same as its name, thus exploding the universe!

 

Working in the opposite direction, (*) is all we need to achieve; as long as you can partition the list of queries into such segments, it corresponds to a plan of saving the universe. You don't even care about which engine is used for one segment; any engine not appearing as a query on that segment will do. However, you might sometimes pick the same engine for two consecutive segments, laughing at yourself when you realize it; why don't I just join the two segments into one? Because your task is to use as few segments as possible, it is obvious that you want to make each segment as long as possible.

This leads to the greedy solution: Starting from the first query, add one query at a time to the current segment until the names of all S search engines have been encountered. Then we continue this process in a new segment until all queries are processed.

Sample code in C++, where st is the set of queries in the current segment, q is the next query, and count is the number of switches.

st.clear();
count = 0;
for (int i=0; i<Q; i++) {
getline(cin, q);
if (st.find(q) == st.end()) {
if (st.size() == S-1) {
st.clear();
count++;
}
st.insert(q);
}
}
If st is a hashset, you expect the solution run in O(n) time. Note that this solution uses the fact that each query will be a search engine name and so we can ignore the list of names provided in the input.

 

Let us justify that the greedy approach always gives the optimal answer. Think of the procedure as Q steps, and we want to show that, for each i, there is (at least) one optimal choice which agrees with us on the first i steps. We do this inductively for i = 0, then i = 1, and so on. The proposition for i = Q when proven true will imply that our algorithm is correct.

So, the key points in the inductive step i:

  1. If adding the next query will explode the universe, we must start a new segment. Any optimal choice agrees with us for the first (i-1) steps must also do that.
  2. If adding the next query will not explode the universe, we do not start a new segment. We know there is an optimal solution R agreed with us for (i-1) steps. Even if in R a new segment is started at step i, we can modify it a little bit. Let R' be the plan that agrees with R, but instead of starting a new segment on the i-th step, we delay this to the (i+1)st. It is clear that R' will also make the universe safe, and has no more switches than R does. So, R' is also an optimal solution, and agrees with our choice for the first i steps.

 

The similar lines of justifications work for many greedy algorithms, including the well beloved minimum spanning trees.
 
Another DP Solution:

Def. Cost[k][i] as the min switches
when k queries come and current search engine is i

0<=i<=S
0<=k<=Q

1. Optimal: if i!=id[k]: Cost[k][i]=min{..., Cost[k-1][i-2]+1, Cost[k-1][i-1]+1, Cost[k-1][i], Cost[k-1][i+1]+1, Cost[k-1][i+2]+1,...}

    else: Cost[k][i]=min{..., Cost[k-1][i-2]+1, Cost[k-1][i-1]+1, Cost[k-1][i+1]+1, Cost[k-1][i+2]+1,...}

2. Init: Cost[0][i]=0


Source Code
#include <hash_set>
#include 
<iostream>

using namespace std;

#define Rep(i,n) for (int i(0),_n(n); i<_n; ++i)

int main()
{
    
int T;
    
//freopen("..\\s.in","r",stdin);
    
//freopen("..\\s.out","w",stdout);
    scanf("%d"&T);
    Rep(t, T) 
{
        
int S;
        scanf(
"%d"&S);
        
string q;
        getline(cin, q);
//a unread '\n' in scanf
        Rep(i, S) {
            getline(cin, q);
        }

        
int Q;
        scanf(
"%d"&Q);
        getline(cin, q);

        stdext::hash_set
<string> st;
        
int count = 0;
        Rep(i, Q) 
{
            getline(cin, q);
            
if (st.find(q) == st.end()) {
                
if (st.size() == S-1{
                    st.clear();
                    count
++;
                }

                st.insert(q);
            }

        }

        
        printf(
"Case #%d: %d\n", t+1, count);
    }

}

posted on 2009-08-12 21:20 Chauncey 閱讀(318) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


導航

<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

統計

常用鏈接

留言簿

隨筆檔案(4)

文章檔案(3)

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产精品免费| 欧美影院一区| 激情婷婷亚洲| 久久网站免费| 亚洲激情视频网| 欧美日韩国产精品一卡| 国产精品美腿一区在线看| 亚洲精品国产精品乱码不99按摩| 亚洲日韩中文字幕在线播放| 国产日韩一区欧美| 国产午夜精品全部视频播放| 国产一区二区中文字幕免费看| 国内精品久久久久久久果冻传媒 | 国产精品日韩一区二区三区| 欧美一区二区三区免费视| 国产欧美午夜| 精品成人免费| 99国产麻豆精品| 欧美一区二区黄| 老司机aⅴ在线精品导航| 亚洲欧洲综合| 亚洲一区二区日本| 久久久久久9999| 欧美日韩专区在线| 激情欧美日韩| 亚洲系列中文字幕| 久久亚洲综合色| 中文日韩电影网站| 蘑菇福利视频一区播放| 国产日韩欧美视频在线| 亚洲精品国产精品国自产在线| 欧美一区二区三区在线视频 | 亚洲国产天堂久久综合网| 一区二区欧美国产| 久久精品在线视频| 国产精品性做久久久久久| 9久re热视频在线精品| 久久九九精品| 国产精品99久久久久久久女警| 久久久亚洲午夜电影| 国产精品日日摸夜夜添夜夜av| 亚洲精品一区二区三区蜜桃久| 久久久久成人精品| 亚洲视频一区在线| 欧美日韩三级在线| 亚洲国产一区二区三区高清| 久久精品夜夜夜夜久久| 一本色道精品久久一区二区三区| 久久久亚洲成人| 国产精品免费小视频| 亚洲视频在线观看视频| 欧美激情一区二区三级高清视频 | 亚洲经典自拍| 乱中年女人伦av一区二区| 国产一区三区三区| 欧美一级大片在线免费观看| 亚洲天堂第二页| 欧美日韩在线综合| 一区二区三区日韩精品视频| 欧美肥婆bbw| 女同一区二区| 夜夜嗨av一区二区三区四季av| 亚洲福利一区| 欧美激情中文不卡| 亚洲毛片在线看| 亚洲免费高清| 欧美日韩一区二区三区| 欧美激情一区二区三区| 亚洲精品日韩一| 欧美成人午夜77777| 久久黄色网页| 极品裸体白嫩激情啪啪国产精品| 久久精品成人一区二区三区蜜臀| 亚洲欧美日韩直播| 在线 亚洲欧美在线综合一区| 玖玖玖免费嫩草在线影院一区| 久久久99精品免费观看不卡| 国产综合香蕉五月婷在线| 蜜臀av在线播放一区二区三区| 久久精品日韩| 亚洲美女电影在线| 亚洲午夜性刺激影院| 国产午夜精品全部视频播放 | 久久精品国产亚洲精品| 精品88久久久久88久久久| 裸体丰满少妇做受久久99精品| 久久综合九色九九| 亚洲精品欧美| 亚洲午夜电影在线观看| 一区二区三区我不卡| 亚洲精品老司机| 国产精品性做久久久久久| 免费的成人av| 欧美色图麻豆| 久久久夜精品| 欧美精品1区2区3区| 性色一区二区| 久久免费国产| 亚洲一区二区三区色| 久久国产精品99久久久久久老狼| 亚洲国产三级网| 亚洲一级一区| 亚洲欧洲综合| 欧美怡红院视频| 一本到12不卡视频在线dvd| 欧美一区二区三区精品| 一区二区三区日韩| 免费不卡在线观看av| 午夜欧美大片免费观看| 男女激情视频一区| 久久精品国产久精国产爱| 欧美激情一区二区三区蜜桃视频| 久久成人精品无人区| 欧美日韩一区三区| 亚洲大片精品永久免费| 国产一区二区三区久久悠悠色av| 亚洲精品中文字幕有码专区| 精品成人国产| 欧美在线看片| 久久xxxx| 国产九九视频一区二区三区| 日韩视频一区二区三区在线播放免费观看 | 久久一区亚洲| 亚洲免费高清视频| 久久香蕉国产线看观看网| 欧美一级午夜免费电影| 性欧美video另类hd性玩具| 亚洲男人的天堂在线| 久久性色av| 欧美日韩国产三级| 99re亚洲国产精品| 亚洲日本乱码在线观看| 久色成人在线| 午夜在线视频观看日韩17c| 99re热这里只有精品视频 | 国产精品婷婷| 99精品视频免费| 久久精品30| 亚洲精品中文字幕在线| 欧美夫妇交换俱乐部在线观看| 99国产精品一区| 亚洲免费影视第一页| 久久精品国产999大香线蕉| 午夜精品国产更新| 亚洲综合精品一区二区| 亚洲欧美日韩一区在线| 蜜臀久久99精品久久久画质超高清| 99精品久久久| 午夜亚洲视频| 午夜视频在线观看一区二区三区| 欧美日本不卡高清| 91久久精品美女高潮| 亚洲大片一区二区三区| 免费成人激情视频| 亚洲人精品午夜| 亚洲精品久久久蜜桃| 欧美日本乱大交xxxxx| 一区二区三区欧美在线| 久久成人亚洲| 亚洲国产精品高清久久久| 欧美ab在线视频| 一本大道av伊人久久综合| 香蕉亚洲视频| 狠狠色综合一区二区| 免费成人av| 亚洲小说区图片区| 久久夜色精品国产| 亚洲精品乱码久久久久久日本蜜臀 | 亚洲伦伦在线| 欧美在线高清视频| 亚洲福利国产| 麻豆精品在线观看| 欧美影院在线播放| 亚洲国产高潮在线观看| 亚洲人成毛片在线播放| 欧美日韩调教| 性欧美精品高清| 亚洲国产另类精品专区| 亚洲专区国产精品| 在线看国产一区| 国产精品卡一卡二| 麻豆精品国产91久久久久久| 在线一区日本视频| 欧美va天堂va视频va在线| 亚洲一区二区三区精品视频| 国产视频一区三区| 国产精品国产精品| 模特精品在线| 久久av一区二区三区亚洲| 亚洲精品在线一区二区| 麻豆精品视频在线观看视频| 亚洲一区成人| 国产精品网红福利| 在线一区视频| 欧美国产先锋| 久久五月婷婷丁香社区| 亚洲一区国产精品| 一区二区激情视频| 91久久精品国产91性色| 激情视频一区|