Codeforces 38F-Smart Boy

Smart Boy
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Once Petya and Vasya invented a new game and called it "Smart Boy". They located a certain set of words — the dictionary — for the game. It is admissible for the dictionary to contain similar words.

The rules of the game are as follows: first the first player chooses any letter (a word as long as 1) from any word from the dictionary and writes it down on a piece of paper. The second player adds some other letter to this one's initial or final position, thus making a word as long as 2, then it's the first player's turn again, he adds a letter in the beginning or in the end thus making a word as long as 3 and so on. But the player mustn't break one condition: the newly created word must be a substring of a word from a dictionary. The player who can't add a letter to the current word without breaking the condition loses.

Also if by the end of a turn a certain string s is written on paper, then the player, whose turn it just has been, gets a number of points according to the formula:

where

  •  is a sequence number of symbol c in Latin alphabet, numbered starting from 1. For example, , and .
  •  is the number of words from the dictionary where the line s occurs as a substring at least once.

Your task is to learn who will win the game and what the final score will be. Every player plays optimally and most of all tries to win, then — to maximize the number of his points, then — to minimize the number of the points of the opponent.

Input

The first input line contains an integer n which is the number of words in the located dictionary (1 ≤ n ≤ 30). The n lines contain the words from the dictionary — one word is written on one line. Those lines are nonempty, consisting of Latin lower-case characters no longer than 30 characters. Equal words can be in the list of words.

Output

On the first output line print a line "First" or "Second" which means who will win the game. On the second line output the number of points of the first player and the number of points of the second player after the game ends. Separate the numbers by a single space.

Examples
input
Copy
2
aba
abac
output
Second
29 35
input
Copy
3
artem
nik
max
output
First
2403 1882


题意:有n个只由小写字母组成的字符串,两个人轮流从一个空字符串开始构造字符串,要求每个人在其操作轮要加一个字符在已有字符串前面或者后面使得这个字符串依旧是这n个字符串中某些字符串的子串,如果没有合法方案则该人失败,否则该人得分,假设该人操作后字符串为s,则本轮得分Score(s)=(∑i=1|s|value(si))∗max1≤i≤|s|{|value(si)}+num(s),其中value(c)为c在26个字母中的位置,即value(′a′)=1,value(′z′)=26num(s)为这n个字符串中以s为子串的字符串数量,每个人在操作时采取最优策略让自己赢,且在保证自己赢的情况下使得自己得分最高,在保证自己赢且得分最高的情况下使得对方得分尽可能少,问最后哪一个人赢以及两个人的得分

解题思路:由于字符串数量和长度都不超过30,不同子串数不多,预处理出每个子串的num,之后对所有可能的情况记忆化搜索即可


#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <string>  
#include <algorithm>  
#include <map>  
#include <set>
#include <stack>  
#include <queue>  
#include <vector>  
#include <bitset>  
#include <functional>  

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;

struct node
{
	int sg, sum1, sum2;
	bool operator < (const node &x)const
	{
		if (sg != x.sg) return sg < x.sg;
		if (sum1 != x.sum1) return sum1 < x.sum1;
		return sum2 > x.sum2;
	}
};

set<string>S;
map<string, node>mp;
map<string, int>num;

int get(string s)
{
	int ans = 0, mx = 0, len = s.length();
	for (int i = 0; i < len; i++)
	{
		ans += s[i] - 'a' + 1;
		mx = max(mx, s[i] - 'a' + 1);
	}
	return ans * mx + num[s];
}

node dfs(string s)
{
	if (mp.find(s) != mp.end()) return mp[s];
	node ans = { 0, 0, 0 };
	for (int i = 0; i < 26; i++)
	{
		string ss = s + char('a' + i);
		if (S.find(ss) != S.end())
		{
			node tmp = dfs(ss);
			swap(tmp.sum1, tmp.sum2);
			tmp.sg ^= 1;
			tmp.sum1 += get(ss);
			if (ans < tmp) ans = tmp;
		}
		ss = char('a' + i) + s;
		if (S.find(ss) != S.end())
		{
			node tmp = dfs(ss);
			swap(tmp.sum1, tmp.sum2);
			tmp.sg ^= 1;
			tmp.sum1 += get(ss);
			if (ans < tmp) ans = tmp;
		}
	}
	return mp[s] = ans;
}

int main()
{
	int n, len;
	string s, ss;
	while (~scanf("%d", &n))
	{
		for (int i = 1; i <= n; i++)
		{
			cin >> s;
			set<string>tmp;
			len = s.length();
			for (int j = 0; j < len; j++)
			{
				for (int k = j; k < len; k++)
				{
					ss = s.substr(j, k - j + 1);
					S.insert(ss);
					if (tmp.find(ss) == tmp.end())
					{
						tmp.insert(ss);
						num[ss]++;
					}
				}
			}
		}
		node ans = dfs("");
		if (ans.sg) printf("First\n");
		else printf("Second\n");
		printf("%d %d\n", ans.sum1, ans.sum2);
	}
	return 0;
}
点点多人视频空间是dd5588推出的集视频聊天、游戏、远程会议,互动娱乐与一体的大型综合娱乐平台。平台汇聚大量网络明星、歌手和美女主持,更带来互动交友和视频游戏功能,给所有的网友们带来网络K歌,飚歌,游戏,会议,交友的全新网络生活。   9.1版本更新说明:   1、新增数款休闲游戏。   2、更换音视频流解码,不降低音质,网络更通畅。   3、增加添加区长,副区长模块。   4、完整查询个人所有礼品流水,房间人气功能。   5、多麦序功能,掉线后自动恢复麦序。   6、增加座驾功能。   视频窗口可以运用各种虚拟视频的特效功能让呈现效果变得更加炫目。      双线互通让聊天畅通无阻二视频房间全部为双线互通,即网通电信互联互通,让用户体验沟通中的绝对“零”距离。   核心功能:   免费多方视频聊天娱乐免费高清晰全视频、全音频沟通,随时随地畅聊无限,可随时邀请好友进行点对点聊天或进入聊天室交流。   多人同时语音,网络party,声色共享,好友沟通绝对“零”距离,不被打扰的私密空间。   多人视频聊天室精彩不断,两路视频、语音,排麦及主持机制,优质的立体声音频效果,更有300人容量的视频群体娱乐大舞台。   最生动的虚拟礼物轻松点击即可赠送好友,传情达意尽享交友乐趣。   视频休闲游戏乐趣无穷点点聊天室客户端面板可直接点击进入游戏大厅登陆面板,多种棋牌娱乐游戏供您选择;可以视频语音的休闲游戏,体会面对面的游戏快感。   超级交友平台,让您即时体验粉红男女浪漫遭遇的感觉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值