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

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>
            精品盗摄一区二区三区| 影音欧美亚洲| 午夜国产一区| 亚洲午夜一区二区三区| 国产精品三级视频| 欧美在线啊v| 久久精品中文字幕一区| 在线观看一区二区视频| 亚洲夫妻自拍| 欧美日本在线观看| 欧美一区二区三区在线播放| 欧美在线亚洲一区| 亚洲激情视频在线播放| 一本色道久久加勒比精品| 国产精品久久中文| 美女精品国产| 欧美精选一区| 久久久久久精| 欧美日本一区二区高清播放视频| 亚洲一区二区三区四区视频| 亚洲欧美日韩国产中文| 在线播放日韩| 国产精品99久久久久久久久| 国内精品久久久久影院色| 亚洲国产精品尤物yw在线观看| 国产精品激情| 麻豆91精品| 欧美亚洲第一页| 男人天堂欧美日韩| 国产精品每日更新| 欧美大片在线观看| 国产精品美女久久久久久久 | 国内外成人免费激情在线视频网站 | 亚洲国产网站| 亚洲在线播放电影| 亚洲国产精品欧美一二99| 在线视频欧美一区| 在线观看国产成人av片| 亚洲天堂av在线免费观看| 91久久精品一区| 性欧美超级视频| 亚洲免费影院| 欧美日本韩国一区二区三区| 久久影音先锋| 国产日韩精品一区| 一本大道久久a久久精品综合| 一区二区三区在线免费视频| 亚洲视频免费看| 99天天综合性| 欧美成人精精品一区二区频| 久久先锋影音| 国内精品伊人久久久久av影院| 99精品黄色片免费大全| 亚洲精品视频一区二区三区| 久久精品一区二区三区不卡| 午夜精品久久久久久久久久久久久 | 欧美视频观看一区| 亚洲国产福利在线| 在线日韩欧美| 久久免费国产精品| 久久一区二区三区四区五区| 国产精品视频99| 亚洲网站啪啪| 亚洲欧美综合另类中字| 欧美视频日韩视频在线观看| 日韩午夜av| 亚洲无线视频| 国产精品高清免费在线观看| 夜夜嗨av一区二区三区四季av | 亚洲另类在线视频| 久久中文在线| 亚洲电影毛片| 日韩视频一区二区三区在线播放免费观看 | 影音先锋日韩资源| 久久久久在线| 欧美激情一区二区三区不卡| 最新热久久免费视频| 女人天堂亚洲aⅴ在线观看| 欧美大秀在线观看| 亚洲卡通欧美制服中文| 欧美黄色一级视频| 亚洲日本免费| 亚洲欧美日产图| 国产午夜精品久久久久久免费视| 欧美在线观看一区二区| 免费亚洲婷婷| 在线视频免费在线观看一区二区| 欧美午夜免费影院| 亚洲综合视频网| 另类春色校园亚洲| 99re热这里只有精品视频| 欧美日韩精品免费观看视一区二区 | 欧美国产精品久久| 亚洲精品在线电影| 欧美一级在线播放| 在线精品视频免费观看| 欧美日本在线一区| 性亚洲最疯狂xxxx高清| 欧美高清在线| 欧美亚洲网站| 亚洲激情成人在线| 国产精品午夜国产小视频| 久久久久国产一区二区三区| 日韩视频一区二区三区在线播放免费观看 | 欧美一进一出视频| 亚洲激精日韩激精欧美精品| 国产精品xxxxx| 快播亚洲色图| 亚洲欧美日韩国产一区| 欧美激情中文字幕一区二区| 午夜在线精品| 亚洲日本视频| 国产一区二区三区电影在线观看| 欧美成人激情视频免费观看| 亚洲欧美日韩区| 亚洲精品久久久蜜桃| 久久综合九九| 午夜精品视频在线观看| 亚洲欧洲在线视频| 国产午夜精品理论片a级大结局| 欧美美女视频| 久久综合中文色婷婷| 亚洲欧美电影院| 夜色激情一区二区| 亚洲高清不卡av| 蜜臀av一级做a爰片久久| 亚洲欧美日韩直播| 亚洲视频在线观看免费| 亚洲国产一二三| 在线播放豆国产99亚洲| 国产日产亚洲精品系列| 国产精品成人在线| 欧美日韩福利在线观看| 欧美成人精品一区二区三区| 久久精品亚洲精品| 午夜免费久久久久| 亚洲女ⅴideoshd黑人| 中文精品一区二区三区| 亚洲看片免费| 99人久久精品视频最新地址| 亚洲精选在线| 亚洲伦理中文字幕| 亚洲精品乱码久久久久久按摩观| 欧美电影资源| 欧美大片在线看免费观看| 欧美成ee人免费视频| 欧美国产激情二区三区| 欧美激情精品久久久久久蜜臀 | 久久久久久久久久久成人| 亚洲免费一区二区| 亚洲永久在线观看| 午夜精品福利在线| 午夜精品一区二区三区四区| 亚洲欧美大片| 欧美综合国产精品久久丁香| 午夜一区二区三区在线观看| 欧美一区二区三区男人的天堂| 午夜欧美视频| 久久精品天堂| 老司机亚洲精品| 亚洲国产精品va在线观看黑人| 亚洲激情一区二区三区| 亚洲九九九在线观看| 亚洲一区三区在线观看| 欧美伊人久久大香线蕉综合69| 久久精品亚洲国产奇米99| 免费欧美在线视频| 欧美日韩综合在线免费观看| 国产伦精品一区二区| 一区精品在线播放| 9色精品在线| 欧美一区=区| 欧美成人午夜激情| 亚洲日本欧美日韩高观看| 亚洲一区成人| 久久久水蜜桃| 欧美视频中文字幕在线| 红桃视频国产精品| 中国成人亚色综合网站| 久久精品一区二区三区四区 | 日韩亚洲欧美中文三级| 亚洲综合视频网| 欧美高清视频一区| 国产精品一区二区在线观看网站 | 免播放器亚洲一区| 99精品欧美一区| 久久久久久黄| 国产精品久久一区主播| 亚洲国产欧美一区| 欧美一级播放| 亚洲乱码日产精品bd| 久久国产乱子精品免费女| 欧美精品一区二区三区蜜臀| 国产欧美精品日韩| 99国内精品久久久久久久软件| 久久久久国产一区二区| 99re66热这里只有精品4| 久久久青草青青国产亚洲免观| 国产精品免费观看在线| 亚洲精品无人区|