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

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 閱讀(324) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


導(dǎo)航

<2009年8月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
303112345

統(tǒng)計

常用鏈接

留言簿

隨筆檔案(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>
            亚洲一区二区在线视频| 午夜亚洲激情| 欧美va天堂| 亚洲国产精品欧美一二99| 免费一级欧美片在线观看| 久久动漫亚洲| 久久国产日韩欧美| 在线成人激情| 亚洲国产99精品国自产| 亚洲激情网站免费观看| 欧美国产精品劲爆| 欧美精品在线一区二区| 亚洲专区一区二区三区| 先锋影音久久| 亚洲欧洲在线视频| 亚洲午夜av在线| 一区二区三区在线观看国产| 亚洲第一精品在线| 亚洲激情小视频| 欧美在线观看视频在线| 欧美日韩视频在线一区二区| 韩国成人精品a∨在线观看| 久热国产精品视频| 亚洲欧美中文日韩v在线观看| 欧美mv日韩mv亚洲| 欧美三区在线| 久久手机免费观看| 这里只有精品视频| 欧美激情91| 亚洲国产综合在线| 一区二区三区欧美在线观看| 狠狠色丁香婷婷综合久久片| 亚洲日韩第九十九页| 久久综合一区二区| 在线看国产一区| 在线视频日韩精品| 欧美三级电影大全| 在线综合亚洲欧美在线视频| 91久久综合| 国产原创一区二区| 999在线观看精品免费不卡网站| 国模一区二区三区| 国产精品99久久99久久久二8| 亚洲成人在线| 欧美一区二区精美| 国内视频精品| 久久综合九色综合网站 | 久久人人精品| 欧美午夜无遮挡| 欧美国产先锋| 狠狠久久婷婷| 亚洲男人的天堂在线| 一本色道久久综合一区| 麻豆久久婷婷| 麻豆精品传媒视频| 国语自产精品视频在线看| 亚洲一区二区在线观看视频| 国产美女精品视频免费观看| 欧美一级视频免费在线观看| 欧美精品一区二区三区视频| 亚洲少妇在线| 欧美激情综合五月色丁香小说| 美日韩在线观看| 一区视频在线播放| 久久久精品一区| 久久久久久久999| 亚洲欧美国产另类| 欧美中文在线视频| 久久久亚洲高清| 久久视频在线免费观看| 久久成人18免费网站| 久久精品99国产精品| 国产一区视频网站| 欧美一区午夜精品| 亚洲免费av片| 欧美另类人妖| 亚洲美女诱惑| 亚洲综合999| 另类激情亚洲| 亚洲激情一区二区| 一本一本久久a久久精品综合妖精| 亚洲视频欧美视频| 亚洲国产精品日韩| 午夜欧美不卡精品aaaaa| 国产日韩精品一区二区| 午夜精品久久久久久久99樱桃| 亚洲国产导航| 亚洲免费小视频| 亚洲精品色图| 亚洲欧美日韩国产成人精品影院| 久久精品一区二区三区不卡牛牛| aa日韩免费精品视频一| 欧美一区激情| 亚洲女人天堂成人av在线| 国产免费一区二区三区香蕉精| 欧美一区二区三区视频免费播放| 免费欧美网站| 国产精品一区一区三区| 久久爱www| 久久成人一区二区| 在线观看成人网| 欧美亚洲日本网站| 最新日韩在线视频| 在线观看久久av| 欧美日韩一卡| 亚洲日本一区二区| 亚洲国产成人av| 国产精品久久久久aaaa樱花| 久久9热精品视频| 日韩视频在线免费观看| 亚洲精品在线看| 国产亚洲一级高清| 欧美精品导航| 亚洲国产你懂的| 亚洲黄色三级| 国产深夜精品福利| 午夜精品久久久久久久男人的天堂| 在线综合亚洲| 欧美亚男人的天堂| 浪潮色综合久久天堂| 欧美+日本+国产+在线a∨观看| 亚洲午夜精品久久久久久浪潮| 黑人极品videos精品欧美裸| 欧美午夜久久久| 99伊人成综合| 亚洲欧美国产精品va在线观看| 激情久久久久久| 欧美jizzhd精品欧美巨大免费| 亚洲欧美乱综合| 久久性色av| 欧美一区二区三区电影在线观看| 国产乱码精品一区二区三区av| 欧美成人午夜影院| 久久综合免费视频影院| 亚洲成人在线网站| 久热综合在线亚洲精品| 影音先锋日韩有码| 国产亚洲精品7777| 久久综合久色欧美综合狠狠 | 美日韩精品视频| 国产精品一区二区三区久久久| 欧美精品一区二区三区一线天视频| 久久久久免费观看| 久久久精品五月天| 久久久91精品国产一区二区三区| 国内久久视频| 国内揄拍国内精品少妇国语| 国产精品亚洲精品| 久久久久国产精品一区三寸| 性做久久久久久免费观看欧美| 亚洲一区精品视频| 午夜精品久久久久影视| 欧美激情在线狂野欧美精品| 中日韩男男gay无套| 一区二区高清在线| 亚洲视频专区在线| 性感少妇一区| 久久九九国产精品怡红院| 亚洲日本无吗高清不卡| 日韩一级片网址| 亚洲一区二区三区在线看| 亚洲欧美亚洲| 好看的日韩视频| 亚洲国产精品123| 欧美另类女人| 国产精品久久999| 国产日韩欧美精品在线| 伊甸园精品99久久久久久| 日韩视频欧美视频| 午夜宅男欧美| 夜夜嗨av一区二区三区四区| 亚洲视频二区| 久久精品视频免费播放| 亚洲在线国产日韩欧美| aa国产精品| 一本久道久久综合中文字幕| 久久久噜噜噜久久人人看| 久久久999成人| 一区二区电影免费观看| 亚洲女人天堂av| 久久青草福利网站| 欧美日韩国产精品一卡| 国产日韩一区二区三区| 国产精品激情电影| 欧美久久影院| 国产日韩欧美一区二区三区在线观看 | 亚洲福利在线看| 亚洲午夜久久久| 日韩亚洲综合在线| 欧美中文字幕在线| 亚洲欧美日韩网| 欧美va亚洲va日韩∨a综合色| 久久久久久久久久久一区 | 亚洲第一天堂av| 洋洋av久久久久久久一区| 久久一二三四| 久久男人资源视频| 日韩视频中文| 一本大道久久a久久精品综合 | 亚洲精品国产拍免费91在线|