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

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>
            亚洲三级观看| 国产亚洲精品久久久久动| 免费成人av在线| 先锋资源久久| 一区二区三区高清| 国产精品99久久久久久久vr| 亚洲视频在线一区| 午夜久久tv| 欧美一区免费视频| 久久综合九色综合久99| 嫩草国产精品入口| 亚洲二区在线| 日韩一级在线观看| 亚洲一区二区三区成人在线视频精品 | 欧美一区三区三区高中清蜜桃| 亚洲五月六月| 欧美一区二区三区在线观看 | 农村妇女精品| 久久夜精品va视频免费观看| 亚洲成色777777在线观看影院| 亚洲国产高清视频| 亚洲午夜激情| 麻豆精品视频在线| 国产精品v片在线观看不卡| 国产区日韩欧美| 亚洲精品一区二区三区婷婷月| 亚洲一本大道在线| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲国产精品视频| 欧美亚洲午夜视频在线观看| 免费观看成人www动漫视频| 欧美性片在线观看| 亚洲缚视频在线观看| 亚洲欧美精品suv| 欧美激情中文字幕一区二区| 亚洲综合99| 欧美风情在线观看| 好吊色欧美一区二区三区四区| 一区二区三区日韩精品| 久久人人爽人人爽| 一级日韩一区在线观看| 女人香蕉久久**毛片精品| 国产精品一区二区三区免费观看| 最新中文字幕亚洲| 久久久精品国产99久久精品芒果| 日韩一区二区久久| 欧美激情精品久久久久久蜜臀| 韩国一区二区在线观看| 亚洲欧美日韩国产成人| 亚洲级视频在线观看免费1级| 欧美一乱一性一交一视频| 欧美视频国产精品| 中文欧美日韩| 91久久久久久久久| 久久综合999| 在线播放不卡| 噜噜噜91成人网| 久久精品一本久久99精品| 欧美14一18处毛片| 久久精品国产亚洲5555| 国产一区日韩一区| 久久精品一二三区| 欧美在线91| 国产亚洲欧美一区二区三区| 欧美一区在线直播| 欧美一区二区高清| 精品不卡一区| 欧美第一黄网免费网站| 久久夜精品va视频免费观看| 在线成人激情| 亚洲第一中文字幕在线观看| 蘑菇福利视频一区播放| 亚洲精品一区在线| 亚洲精品午夜| 国产精品成人免费视频| 国产精品一区二区在线观看网站| 中国亚洲黄色| 亚洲婷婷综合色高清在线| 国产精品videosex极品| 亚洲欧美另类国产| 亚洲欧美久久| 国产精品一区二区女厕厕| 久久精品视频免费| 久久先锋影音av| 91久久精品国产91久久性色tv| 亚洲成色777777在线观看影院| 欧美风情在线观看| 亚洲综合欧美| 欧美在线视频不卡| 亚洲精品韩国| 亚洲图片你懂的| 韩日在线一区| 亚洲精品在线视频| 国产乱子伦一区二区三区国色天香| 久久精品成人欧美大片古装| 久久亚洲精品视频| 国产精品99久久久久久有的能看| 亚洲欧美一区二区原创| 亚洲第一精品夜夜躁人人爽| 亚洲高清在线视频| 欧美亚洲第一页| 麻豆视频一区二区| 国产精品成人aaaaa网站| 欧美中文字幕视频| 欧美va亚洲va香蕉在线| 亚洲中字在线| 久久综合成人精品亚洲另类欧美| 亚洲视频精选| 久久亚洲二区| 欧美在线观看一区二区三区| 欧美成年人视频网站欧美| 翔田千里一区二区| 欧美精品久久99| 久久久水蜜桃av免费网站| 欧美日韩免费在线视频| 久久婷婷丁香| 欧美午夜精品久久久久免费视| 欧美成人国产一区二区| 国产精品扒开腿做爽爽爽视频| 农村妇女精品| 国产亚洲欧美色| 亚洲一区不卡| 一区二区日韩精品| 免费在线观看一区二区| 欧美在线|欧美| 国产精品毛片一区二区三区 | 久久成人免费电影| 亚洲精品乱码久久久久| 国内精品久久久久影院色| 亚洲视频在线看| 一区二区三区高清| 欧美国产日韩在线| 欧美国产视频在线| 亚洲第一福利视频| 久久久久国色av免费观看性色| 欧美亚洲综合网| 国产精品成人免费| 久久这里有精品视频| 欧美日韩精品综合在线| 亚洲成人资源| 影音国产精品| 久久国产一区二区| 久久久之久亚州精品露出| 国产毛片一区| 香蕉免费一区二区三区在线观看| 午夜精品久久99蜜桃的功能介绍| 欧美日韩精品免费看| 亚洲欧洲一区二区天堂久久| 亚洲国产精品成人va在线观看| 久久久久久亚洲精品中文字幕| 久久亚洲一区二区| 韩国欧美国产1区| 蜜臀av在线播放一区二区三区| 欧美成人69av| 亚洲精品女人| 欧美日韩在线视频观看| 中文精品视频一区二区在线观看| 亚洲天天影视| 国产免费观看久久| 久久福利毛片| 亚洲国产婷婷香蕉久久久久久99| 亚洲精品小视频在线观看| 欧美日韩天天操| 午夜伦欧美伦电影理论片| 久久综合久久美利坚合众国| 亚洲精品亚洲人成人网| 国产精品国产三级国产普通话99| 亚洲一本大道在线| 免费永久网站黄欧美| 日韩一区二区电影网| 国产精品视频yy9299一区| 欧美在线观看网站| 欧美国产另类| 亚洲一区二区在线免费观看视频 | 久久午夜精品一区二区| 激情成人在线视频| 欧美日韩理论| 久久成人精品电影| 99精品福利视频| 久久精品亚洲一区二区三区浴池| 亚洲国产裸拍裸体视频在线观看乱了中文| 欧美福利在线观看| 欧美亚洲一区在线| 亚洲裸体俱乐部裸体舞表演av| 久久精品av麻豆的观看方式| 99re6热在线精品视频播放速度| 国产精品成人免费视频| 美女主播一区| 亚洲欧美日韩一区| 亚洲另类在线视频| 麻豆精品传媒视频| 亚洲欧美日韩精品在线| 亚洲乱码国产乱码精品精可以看| 国产午夜亚洲精品不卡| 欧美日韩国产小视频在线观看| 久久国产一区二区| 亚洲伊人观看| 亚洲看片网站| 亚洲欧洲日本mm| 欧美高清hd18日本|