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

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 20:25 Chauncey 閱讀(120) 評論(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>
            在线视频欧美精品| 亚洲小说欧美另类婷婷| 国产精品videosex极品| 欧美激情91| 黄色成人在线免费| 午夜日本精品| 亚洲欧美国产精品va在线观看| 另类综合日韩欧美亚洲| 久久国产婷婷国产香蕉| 国产精品久久国产三级国电话系列 | 久久av资源网站| 先锋影音久久久| 欧美午夜大胆人体| 99精品免费视频| 一区二区三区回区在观看免费视频| 美女日韩在线中文字幕| 久久亚洲一区二区三区四区| 国产乱码精品一区二区三区av| 夜夜嗨av色一区二区不卡| 一区二区三区日韩在线观看 | 欧美精品九九| 亚洲欧洲日产国产网站| 亚洲国产cao| 老司机aⅴ在线精品导航| 欧美96在线丨欧| 亚洲高清精品中出| 欧美69wwwcom| 亚洲激情一区二区| av不卡在线| 欧美日韩在线亚洲一区蜜芽| 亚洲精品人人| 亚洲一区二区在线观看视频| 国产精品久久久久久av下载红粉| 在线视频精品一区| 久久av在线| 精品1区2区| 欧美sm视频| 一本色道久久综合亚洲二区三区| 亚洲一区二区欧美| 国产日韩欧美三区| 久久免费视频在线观看| 亚洲国产一成人久久精品| 99精品免费网| 国产精品色婷婷| 久久人人97超碰国产公开结果| 欧美国产1区2区| 亚洲一区二区在线播放| 国产日产欧美精品| 欧美chengren| 亚洲视频国产视频| 欧美91视频| 亚洲一区二区三区四区视频| 国产一区二区三区在线观看免费视频| 久久久无码精品亚洲日韩按摩| 亚洲黄网站黄| 欧美在线国产| 亚洲伦理在线免费看| 国产精品黄色| 欧美成人激情视频| 亚洲一区二区三区午夜| 欧美国产日韩a欧美在线观看| 一区二区三区黄色| 一区二区三区在线不卡| 欧美日精品一区视频| 久久久久国产精品厨房| 日韩视频精品| 欧美黄色aa电影| 欧美在线综合视频| 一本色道久久综合亚洲91| 国产在线一区二区三区四区| 欧美日韩成人一区二区三区| 欧美一区二区三区在线观看视频 | 蜜臀av性久久久久蜜臀aⅴ四虎| 夜夜夜久久久| 亚洲电影免费观看高清完整版在线观看 | 亚洲人体1000| 久久最新视频| 欧美一区二区三区免费观看视频| 亚洲国产精品久久久久| 国产色婷婷国产综合在线理论片a| 欧美国产精品v| 欧美影院成人| 亚洲一区日本| 亚洲最新色图| 亚洲欧洲日本mm| 欧美.com| 噜噜噜在线观看免费视频日韩| 亚洲欧美激情视频| 在线亚洲免费视频| 亚洲精品国产精品国产自| 国一区二区在线观看| 国产欧美精品日韩精品| 国产精品mm| 欧美色另类天堂2015| 欧美大片免费看| 欧美88av| 欧美顶级少妇做爰| 欧美国产日韩一区二区在线观看 | 另类专区欧美制服同性| 欧美影院在线| 久久精品国产清高在天天线| 亚洲欧美日韩国产精品 | 亚洲麻豆av| 日韩亚洲欧美精品| 亚洲久久视频| 一本色道久久综合亚洲精品小说| 亚洲韩国青草视频| 91久久精品日日躁夜夜躁国产| 欧美激情1区2区3区| 欧美寡妇偷汉性猛交| 欧美激情a∨在线视频播放| 欧美a级一区| 亚洲国产精品一区二区久| 亚洲高清久久久| 亚洲欧洲日本专区| 一本久久综合亚洲鲁鲁| 亚洲电影av| 久久黄金**| 快she精品国产999| 在线观看久久av| 亚洲综合国产精品| 午夜精品美女自拍福到在线| 午夜日本精品| 久久精品中文字幕一区二区三区| 久久精品99久久香蕉国产色戒 | 欧美激情2020午夜免费观看| 亚洲黄色片网站| 一区二区冒白浆视频| 亚洲免费在线视频一区 二区| 欧美一区2区视频在线观看| 久久久精品国产免费观看同学| 久久中文字幕一区| 欧美日韩精品久久久| 国产精品一区二区你懂的| 在线观看免费视频综合| 99亚洲视频| 久久国产一区二区三区| 亚洲第一精品福利| 一区二区三区高清在线观看| 久久国产黑丝| 欧美日韩大片一区二区三区| 国产日韩欧美日韩| 日韩一级黄色片| 久久久久久久一区二区三区| 亚洲第一页中文字幕| 亚洲少妇中出一区| 麻豆成人在线观看| 国产精品国产一区二区| 激情91久久| 亚洲永久视频| 欧美激情1区2区| 午夜视频在线观看一区二区三区 | 欧美另类人妖| 国内精品久久久久伊人av| 99国内精品久久| 久久久夜夜夜| 一区二区三区四区在线| 鲁大师成人一区二区三区 | 欧美性一二三区| 亚洲国产99| 久久激情婷婷| 国产精品99久久久久久久久| 蜜臀久久久99精品久久久久久| 国产精品午夜久久| 中文亚洲字幕| 亚洲成色精品| 久久久久久久一区| 国产噜噜噜噜噜久久久久久久久| 一本色道久久精品| 亚洲国产日韩欧美在线99| 欧美在线不卡| 国产啪精品视频| 午夜激情亚洲| 一区二区激情小说| 欧美黄色片免费观看| 亚洲福利一区| 免费国产自线拍一欧美视频| 亚洲欧美日韩一区二区在线| 欧美天天影院| 亚洲视频免费| 日韩一区二区精品视频| 欧美伦理在线观看| 99v久久综合狠狠综合久久| 亚洲第一区色| 欧美黄免费看| 99亚洲一区二区| 亚洲美女91| 欧美日韩一区二区视频在线观看 | 亚洲天堂网在线观看| 欧美午夜www高清视频| 一区二区欧美在线| 99在线热播精品免费| 欧美日韩一区自拍| 亚洲一区在线观看视频 | 欧美xxx成人| 日韩一级黄色大片| 99精品国产福利在线观看免费| 欧美日韩人人澡狠狠躁视频| 亚洲天堂av在线免费| 亚洲视频免费观看|