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

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


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


導航

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

統計

常用鏈接

留言簿

隨筆檔案(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>
            欧美中文字幕精品| 美女精品自拍一二三四| 亚洲日本一区二区三区| 欧美不卡一区| 在线视频亚洲一区| 一区二区三区www| 国产噜噜噜噜噜久久久久久久久| 性欧美精品高清| 欧美一区二区三区视频| 在线观看久久av| 亚洲欧洲日韩女同| 国产精品爽黄69| 美女日韩欧美| 欧美日本亚洲| 久久九九免费视频| 鲁大师影院一区二区三区| 一本色道**综合亚洲精品蜜桃冫| 在线视频你懂得一区二区三区| 国产欧美日韩亚州综合| 美女久久网站| 欧美三级午夜理伦三级中视频| 羞羞色国产精品| 玖玖综合伊人| 亚洲专区一区| 老司机精品久久| 亚洲男人的天堂在线观看| 久久精品一区二区三区中文字幕| 亚洲精品免费电影| 欧美中文字幕久久| 亚洲天堂网站在线观看视频| 久久国产精品久久国产精品| 亚洲免费精品| 久久久精品视频成人| 亚洲免费中文| 欧美精品久久99久久在免费线| 欧美中文字幕| 欧美日韩在线播放一区| 母乳一区在线观看| 国产欧美三级| 一区二区高清视频在线观看| 亚洲电影av在线| 欧美一区二视频| 9国产精品视频| 久热精品视频在线免费观看| 欧美一区二区日韩| 国产精品伦子伦免费视频| 亚洲人成啪啪网站| 91久久嫩草影院一区二区| 欧美一区影院| 欧美一级免费视频| 国产精品毛片大码女人| 日韩午夜在线| 一本色道久久99精品综合| 欧美freesex交免费视频| 免费成人av在线看| 国产一区视频观看| 欧美一级久久| 久久国产夜色精品鲁鲁99| 国产精品swag| 亚洲少妇一区| 亚洲欧美在线免费| 国产精品久久久久久久久婷婷| 亚洲精品乱码久久久久久久久 | 国产日韩欧美一区二区三区在线观看 | 久久综合电影| 国内精品久久久久伊人av| 亚洲综合第一页| 欧美一区二区三区在| 国产伦精品一区二区三区免费| 亚洲一区亚洲| 久久精品国产2020观看福利| 国产欧美一区视频| 欧美一区二区私人影院日本| 久久久亚洲一区| 在线看国产日韩| 欧美成人免费全部| 亚洲美女黄色| 午夜久久99| 国产在线精品成人一区二区三区| 欧美一区二区日韩| 男人的天堂成人在线| 亚洲激情婷婷| 欧美绝品在线观看成人午夜影视| 日韩视频一区二区三区在线播放免费观看 | 欧美1区2区3区| 亚洲人成欧美中文字幕| 欧美精品亚洲精品| 在线视频日韩精品| 久久久久久久久久码影片| 精品69视频一区二区三区| 媚黑女一区二区| aa级大片欧美三级| 久久国产日本精品| 亚洲日韩视频| 国产精品亚洲а∨天堂免在线| 久久成人人人人精品欧| 亚洲国产99精品国自产| 亚洲一线二线三线久久久| 国内综合精品午夜久久资源| 免费成人激情视频| 亚洲欧美成人在线| 亚洲国产精品成人综合| 性伦欧美刺激片在线观看| 亚洲第一福利社区| 国产精品国产三级国产aⅴ入口| 久久久国产午夜精品| 99精品视频免费观看视频| 久久午夜色播影院免费高清| 在线视频欧美日韩精品| 在线观看欧美日韩国产| 欧美体内she精视频在线观看| 久久免费视频这里只有精品| 制服丝袜激情欧洲亚洲| 欧美1区视频| 久久成人av少妇免费| 亚洲九九爱视频| 伊人春色精品| 国产啪精品视频| 欧美日韩亚洲一区二区| 麻豆国产精品va在线观看不卡| 亚洲一区视频在线观看视频| 91久久精品网| 免费人成网站在线观看欧美高清| 午夜影院日韩| 一片黄亚洲嫩模| 亚洲国产欧美日韩精品| 国产一本一道久久香蕉| 国产精品久久久久久久久动漫| 欧美成人精品在线| 久热成人在线视频| 久久精品女人的天堂av| 亚洲欧美日韩精品久久| 一区二区三区国产精华| 亚洲精品黄色| 亚洲激情在线播放| 亚洲第一页在线| 欧美成人免费全部| 美女网站久久| 牛夜精品久久久久久久99黑人| 久久久久国产精品www| 欧美影院精品一区| 久久成人免费日本黄色| 欧美在线免费视屏| 久久久国产精品亚洲一区| 欧美一区2区视频在线观看| 亚洲欧美日韩国产中文| 亚洲欧美激情诱惑| 欧美一区二区久久久| 香蕉乱码成人久久天堂爱免费| 亚洲欧美国产精品桃花| 午夜精品久久| 久久精品国产视频| 久久一区激情| 亚洲高清精品中出| 亚洲精品国产无天堂网2021| 亚洲精品在线一区二区| 一本色道久久加勒比精品| 亚洲视频导航| 欧美一区二区三区男人的天堂| 久久精品国产一区二区三| 母乳一区在线观看| 欧美美女bbbb| 国产欧美不卡| 亚洲第一在线综合网站| 日韩午夜免费| 欧美一区二区三区四区在线观看| 久久久久久穴| 亚洲三级免费观看| 亚洲欧美日韩视频一区| 久久亚洲精品伦理| 欧美日韩亚洲一区二| 国产午夜精品一区二区三区欧美| 在线精品视频免费观看| 宅男66日本亚洲欧美视频| 欧美综合77777色婷婷| 欧美黄色免费网站| 亚洲小说区图片区| 麻豆精品网站| 久久久噜噜噜久久狠狠50岁| 欧美激情欧美激情在线五月| 一本一本a久久| 久久久久99精品国产片| 欧美日韩精品一区二区天天拍小说| 国产精品美女久久久久av超清 | 亚洲欧洲精品天堂一级| 一区二区三区成人| 久久久水蜜桃| 99视频在线观看一区三区| 久久aⅴ国产紧身牛仔裤| 欧美激情成人在线视频| 国产在线一区二区三区四区| 亚洲精品精选| 久久天天躁狠狠躁夜夜av| 99riav1国产精品视频| 久久青青草综合| 国产美女精品| 亚洲视频综合| 亚洲国产精品va在线看黑人| 午夜宅男欧美| 国产精品高精视频免费|