| Wrong Answer | ||||||
| ||||||
| Description | ||||||
| You are solving a crossword puzzle and you have already written down the answers to all questions. While filling in the answers in the diagram, you notice that some answers have overlapping letters that do not match, so you must have made some mistakes in the answers. Instead of checking your answers, you decide to write a computer program to find the maximum number of answers that could have been correct. | ||||||
| Input | ||||||
| The first line of the input contains a single number: the number of test cases to follow. Each test case has the following format: • One line with two integers H and V , satisfying 1 ≤ H, V ≤ 500: the number of horizontal and vertical words, respectively. • H lines, one for each horizontal word, each with two integers x and y and a string W, satisfying 0 ≤ x, y ≤ 1, 000 and 1 ≤ Length(W) ≤ 1, 000: the location of the first letter and the answer. • V lines, one for each vertical word, each with two integers x and y and a string W, satisfying 0 ≤ x, y ≤ 1, 000 and 1 ≤ Length(W) ≤ 1, 000: the location of the first letter and the answer. Integers and strings on the same line are separated by single spaces. No pair of horizontal words will overlap, nor will any pair of vertical words. The words consist of upper case letters only. The top left corner of the diagram is at x = y = 0, x runs in the horizontal direction, and y runs in the vertical direction (downwards). | ||||||
| Output | ||||||
| For every test case in the input, the output should contain a single number, on a single line: the maximum number of answers that can fit in the crossword. | ||||||
| Sample Input | ||||||
| 2 2 2 0 1 BAPC 0 2 LEIDEN 0 0 SOLUTION 2 1 WINNER 1 4 0 1 HELLO 1 0 HI 2 0 BYE 3 0 GOODBYE 4 0 FAREWELL | ||||||
| Sample Output | ||||||
| 3 4 | ||||||
| Hint | ||||||
| The first example below corresponds to the following diagram, where the (assumed) wrong answer is written in italics:
Input Output | ||||||
| Source | ||||||
| BAPC 2010 |
题目大意:
有t组输入 ,接下来两行,表示横着的字符串有多少个,竖着的字符串有多少个,然后接下来那些行每行三个元素,表示起点坐标,和字符串。问最多能够在方格纸上写下多少字符串,并且使其都没有矛盾。
题目保证只有横竖的字符串会有交点。
思路:
1、思考:对于某一个格子,如果当前格子里边有zz种字符的时候,那么这个格子有zz种选择。如果zz==1,毋庸置疑,这个格子没有任何矛盾会出现,不用考虑。那么如果zz>1,那么这个格子就有多重选择。
2、对于zz>1的格子,是有多重选择,那么这个格子到底如何选才能最优呢?我们不急着想如何得到结果,我们首先将样例中的矛盾格子列举出来,我们再继续探究:
(0,1)O、B
(2,1)W、P
对于第一个格子,要么选择O,要么选择B,对于第二个格子,要么选择W,要么选择P,O属于SOLUTION,B属于BAPC,W属于WINNER,P也属于BAPC,显然,如果我们选择O和W是最佳选择,从而抛弃B和P,也就是抛弃这个字符串:BAPC。
这个时候我们不妨将问题向最小点覆盖问题上想,将OB相连,WP相连,构成:
O-B-W的一条链,显然选择B,剩下两个字符串,达到最优。
3、那么问题就简单化了:对于一个格子,我们进行建点建边,用列上边的字符串来匹配行上边的字符串,得到的最大匹配数也就是最小点覆盖数。最小点覆盖数也就等于N-最大独立集
4、那么答案:最大独立集=N-最小点覆盖=N-最大二分匹配数。
AC代码;
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
int map[2][2100][2100];
vector<int >mp[2100];
char a[2100];
int match[2100];
int vis[2100];
int h,l;
int find(int u)
{
for(int i=0; i<mp[u].size(); i++)
{
int v=mp[u][i];
if(vis[v]==0)
{
vis[v]=1;
if(match[v]==-1||find(match[v]))
{
match[v]=u;
return 1;
}
}
}
return 0;
}
void Slove()
{
int output=0;
memset(match,-1,sizeof(match));
for(int i=1; i<=l; i++)
{
memset(vis,0,sizeof(vis));
if(find(i))output++;
}
printf("%d\n",l+h-output);
}
void getmap()
{
memset(map,-1,sizeof(map));
for(int i=1; i<=5000; i++)mp[i].clear();
scanf("%d%d",&h,&l);
for(int i=1; i<=h; i++)
{
int x,y;
scanf("%d%d",&x,&y);
swap(x,y);
scanf("%s",a);
int tmp=strlen(a);
for(int j=0; j<tmp; j++)
{
map[0][x][y]=a[j]-'A';
map[1][x][y]=i;
y++;
}
}
for(int i=1; i<=l; i++)
{
int x,y;
scanf("%d%d",&x,&y);
swap(x,y);
scanf("%s",a);
int tmp=strlen(a);
for(int j=0; j<tmp; j++)
{
if(map[0][x][y]!=a[j]-'A'&&map[0][x][y]!=-1)
{
mp[i].push_back(map[1][x][y]);
}
x++;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
getmap();
Slove();
}
}
探讨解决填字游戏中寻找最大数量无冲突答案的问题,通过分析交叉字母冲突,转化为图论中的最大匹配问题。



被折叠的 条评论
为什么被折叠?



