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

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>
            老鸭窝毛片一区二区三区| 日韩视频永久免费观看| 亚洲精品欧美极品| 国产精品啊啊啊| 免费成人在线视频网站| 亚洲欧美成人网| 一区二区三区成人| 99re6热只有精品免费观看| 亚洲美女电影在线| 一区二区三区免费看| 亚洲午夜激情网页| 欧美在线免费一级片| 久久五月天婷婷| 欧美日韩精品免费观看| 国产精品视频内| 伊人久久婷婷色综合98网| 亚洲黄页视频免费观看| 亚洲视频国产视频| 毛片av中文字幕一区二区| 欧美大片免费观看| 国产精品区一区二区三区| 激情综合亚洲| 午夜久久一区| 亚洲国产99精品国自产| 日韩网站在线观看| 久久一区国产| 国产精品一区=区| 亚洲免费观看高清完整版在线观看熊 | 久久久久综合| 一区二区电影免费观看| 亚洲国产精品久久久久秋霞蜜臀 | 久久国产婷婷国产香蕉| 欧美激情亚洲视频| 久久精品一区二区国产| 国产女优一区| 久久国产精品第一页| 宅男噜噜噜66国产日韩在线观看| 久久精品主播| 国产在线观看91精品一区| 在线视频精品一区| 欧美日韩国产麻豆| 亚洲色诱最新| 亚洲无线一线二线三线区别av| 欧美成人一区二区三区片免费 | 亚洲一区二区动漫| 国产精品高清一区二区三区| 亚洲精品三级| 一本在线高清不卡dvd| 欧美视频在线观看视频极品| 亚洲欧美综合精品久久成人| 亚洲网址在线| 激情校园亚洲| 亚洲欧洲一区二区三区久久| 欧美视频日韩视频| 久久亚洲午夜电影| 欧美国内亚洲| 欧美影视一区| 久久在线91| 欧美制服丝袜| 欧美三级资源在线| 中文av字幕一区| 亚洲一区日韩在线| 亚洲成色777777女色窝| 一区二区三区.www| 亚洲精选久久| 久久精品国产免费观看| 一区二区三区免费看| 久久久免费观看视频| 亚洲网址在线| 欧美激情第一页xxx| 欧美高清视频| 一区三区视频| 久久婷婷av| 久久免费的精品国产v∧| 国产精品伊人日日| 亚洲人成网站在线播| 亚洲人在线视频| 欧美国产一区二区在线观看| 免费成人你懂的| 国产亚洲aⅴaaaaaa毛片| 香蕉免费一区二区三区在线观看| 欧美一级淫片播放口| 国产精品草莓在线免费观看| 亚洲精品视频免费在线观看| 亚洲免费精品| 国产欧美三级| 免费观看一级特黄欧美大片| 亚洲欧洲一区二区三区久久| 99精品国产高清一区二区| 欧美激情91| 小黄鸭视频精品导航| 免费欧美在线视频| 999在线观看精品免费不卡网站| 国产精品v欧美精品∨日韩| 欧美怡红院视频| 欧美日韩国产麻豆| 亚洲少妇在线| 在线观看日韩精品| 欧美大尺度在线| 欧美一级久久久| 亚洲卡通欧美制服中文| 欧美一区不卡| 亚洲你懂的在线视频| 亚洲黄色性网站| 国产亚洲综合在线| 国产精品久久77777| 欧美插天视频在线播放| 亚洲女性裸体视频| 一本大道久久a久久精二百| 欧美大片免费观看| 欧美国产日本在线| 蜜臀久久99精品久久久久久9| 亚洲午夜精品一区二区三区他趣| 亚洲丰满在线| 亚洲国内自拍| 日韩网站在线看片你懂的| 在线播放日韩专区| 亚洲日本欧美| 宅男精品导航| 亚洲欧美卡通另类91av | 亚洲国产成人av在线| 六月婷婷一区| 欧美h视频在线| 91久久视频| a91a精品视频在线观看| 一区二区三区视频在线| 亚洲欧美三级伦理| 久久久久久精| 欧美日韩国产va另类| 国产精品久久福利| 亚洲国产另类久久久精品极度| 亚洲七七久久综合桃花剧情介绍| 9国产精品视频| 香蕉成人伊视频在线观看| 久久人人精品| 日韩一级免费观看| 久久久久久久尹人综合网亚洲| 午夜视频久久久久久| 亚洲欧美日韩区| 久久综合中文| 国产伦精品一区二区三区免费| 在线免费不卡视频| 亚洲一区区二区| 美女视频黄a大片欧美| 99re6这里只有精品| 美女性感视频久久久| 黄色成人av网站| 久久aⅴ国产紧身牛仔裤| 亚洲激情影院| 小嫩嫩精品导航| 国产精品午夜春色av| 亚洲男女自偷自拍| 夜夜嗨av一区二区三区网站四季av | 国产精品日本一区二区| 日韩一级不卡| 99视频有精品| 国产精品国产亚洲精品看不卡15| 日韩网站在线观看| 中文久久乱码一区二区| 欧美三区美女| 夜夜躁日日躁狠狠久久88av| 亚洲第一视频网站| 欧美日本免费| 亚洲影院色无极综合| 欧美一区二区三区在线免费观看 | 欧美日韩国产精品专区| 亚洲精品久久久久久久久久久| 亚洲国产精品va在线看黑人| 久热综合在线亚洲精品| 最新热久久免费视频| 亚洲少妇在线| 亚洲国内在线| 亚洲欧美日韩国产一区二区| 国产精品视频免费观看| 免费成人av在线看| 欧美区二区三区| 国产无一区二区| 久久婷婷丁香| 国产精品magnet| 欧美mv日韩mv国产网站app| 欧美日韩福利在线观看| 免费不卡在线观看| 国产一区二区三区久久| 一本大道久久a久久精二百| 国产精品中文字幕欧美| 亚洲国产精品一区二区www在线| 国产伦精品一区二区三区四区免费 | 久久精品99无色码中文字幕| 亚洲精品资源| 美女999久久久精品视频| 欧美一级在线视频| 国产精品国内视频| 亚洲精品一区二区三区樱花 | 久热精品视频在线观看| 久久久久综合网| 国产欧美日韩亚州综合| 亚洲一区二区三区乱码aⅴ| 亚洲新中文字幕| 国产精品久线观看视频| 性18欧美另类|