[Liiurujia Birthday Match] Q 调试了将近7h的题目
来源:互联网 发布:数控g72编程视频 编辑:程序博客网 时间:2024/05/16 02:14
Problem Q
Quall[e]? Quale?
URL:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=12&page=show_contest&contest=312&mosmsg=Submission+received
Attantion:
目前为止全世界加上我只有仨人过啊目前为止全世界加上我只有仨人过啊目前为止全世界加上我只有仨人过啊目前为止全世界加上我只有仨人过啊
ProblemSet:
If you speak German, you should know the first word in the title. If you speak Italian, you should know the second one :)
Why I use these two words? Because I don't have better choices :( I want my problems' titles to start with A, B, C, etc. This is problem Q so it has to begin with the letter Q.
Sometimes it's difficult. Each problem title has to tell people something about the problem itself, so it can't be arbitrary. If I can't find a suitable title in English, I have to try other languages like Chinese (for example, see the last three problems in Rujia Liu's Present 5 ^_^).
Here is an example.
NoEnglishFrenchChinese1ABC2D-B3CB-4E-E5CA-The title of problem 1 in English starts with A, and the French version starts with B. The Chinese title of problem 1 starts with C. A hyphen means "N/A", so problem 2 doesn't have a French version.
One possible combination is (note that each problem should be used exactly once):
Problem AProblem 1 in EnglishProblem BProblem 3 in FrenchProblem CProblem 5 in EnglishProblem DProblem 2 in EnglishProblem EProblem 4 in ChineseCould you tell me all the possible language combinations? For each combination, all the languages in it must be used (i.e. You can't say the combination is {English,Chinese} if none of the problems actually used the Chinese version).
Input
The first line contains the number of test cases T(T<=500). Each test case begins with two integers n, m(3<=n<=26, 1<=m<=5), the number of problems and the number of languages. The next n lines contains the table containing the first m upper-case letters or '-'. The j-th column in the i-th row in the table is the first letter of the title in the j-th language. A special character '-' means that version does not exist.
Output
For each test case, print all possible combinations in a single line. Each combination is a string of languages used (languages are labeled 1 to m) in increasing order. Shorter combinations should come first. Combinations of the same length should be sorted in increasing order. If the problemset cannot be made, print -1.
Sample Input
45 3ABCD-BCB-E-ECA-3 2ABC--C4 4-A--BB----CC--D-3 4AAAABBBBCCCC
Output for the Sample Input
Case 1: 12 123Case 2: -1Case 3: 23 123 234 1234Case 4: 1 2 3 4 12 13 14 23 24 34 123 124 134 234
问题描述:
给入N * M 的字母和符号矩阵,stri][j] 代表 第 i 个问题 的 第 j 种描述 是 str[i][j] , 问——一共有多少个列的组合,能保证每行取一个数,列都能取到,A~A+N都能取到。
思路历程:
首先听了岛娘的想法直接想到了DLX。一开始想的是把所有的答案都搜出来,然后用解来判断有哪些列满足。TLE。
后来想到了,枚举所有解,然后用DLX判断是否有解。TLE很久了之后嘟嘟嘟嘟大神告诉我我题目读错了,唤起信心继续TLE。但是本机已经能跑完600+个数据无压力。于是尝试着加了一个剪枝之后wa!!!瞬间信心满满。搞了很久之后重新读题+重新看代码。发现一个很简单的地方写错了。改了之后就Accepted了。
解法:
1、预处理所有的列组合,一共31个。
2、预处理所有列组合的分解,比如123 分解成 1 、 2 、 3等等
3、枚举所有列组合,枚举图,然后建DLX图:
第 X 行 代表 第 p 个题目 用第 q 个描述 。
第 1 ~ n 列代表所有的字母,n + 1 列 ~ 2 * n 列代表每一行当且仅当用一次,两个限制。
4、DLX判断是否有解,如果有解则输出。
5、否则输出-1
P.S. 因为每一列都要枚举到,本来应该是前一半用精确覆盖后一半用可重复覆盖。但是如下优化就可以完全用精确覆盖:
在进入 k + 1 层之前, 如果 枚举的列数 - 现在用的列数 > 还剩下的深度(也就是不够枚举了) 那么直接返回 false不进入下一层!!及其重要的剪枝!!!!!!
剪枝:
1、读入图的时候,如果A ~ A + N - 1 的字母不全 , 那么输出-1 !!! 重要剪枝!!!
2、读入图的时候,如果 A + N ~ Z 有字母,那么输出 -1!!! 重要剪枝!!!
3、为了防止mat 数组的reset , 将mat数组设置为int , 加入int ILoveMZ , 每次要更新mat的时候 ++ ILoveMZ , 然后将mat更新元素替换为 ILoveMZ 于是如果当前元素不为ILoveMZ 就不是这次更新的。。。这个小技巧让代码快了 1s
————————————————————整个题目解法到这里就结束了————————————————————
Code:
#define LOCAL/** ` Micro Mezzo Macro Flation -- Overheated Economy ., Ver 0.1 **/#include <functional>#include <algorithm>#include <iostream>#include <fstream>#include <sstream>#include <iomanip>#include <numeric>#include <cstring>#include <cassert>#include <cstdio>#include <string>#include <vector>#include <bitset>#include <queue>#include <stack>#include <cmath>#include <ctime>#include <list>#include <set>#include <map>using namespace std;// <<= ' 0. I/O Accelerator interface .,template<class T> inline T& RD(T &x){ //cin >> x; scanf("%d", &x); //char c; for (c = getchar(); c < '0'; c = getchar()); x = c - '0'; for (c = getchar(); '0' <= c && c <= '9'; c = getchar()) x = x * 10 + c - '0'; //char c; c = getchar(); x = c - '0'; for (c = getchar(); c >= '0'; c = getchar()) x = x * 10 + c - '0'; return x;}typedef vector<int> VI;#define RST(x) memset(x , 0 , sizeof(x))/* .................................................................................................................................. */const int maxN = 26 * 5 + 1 , maxM = 26 + 26 + 1;const int max_size = maxN * maxM;const int inf = 0x3f3f3f3f;int L[max_size], R[max_size], U[max_size], D[max_size], CH[max_size], RH[max_size];int S[maxM], O[maxM];int head, size;int node(int up, int down, int left, int right) { U[size] = up, D[size] = down; L[size] = left, R[size] = right; D[up] = U[down] = R[left] = L[right] = size; return size++;}int ILoveMZ;int mat[maxN][maxM];void init(int N, int M) { size = 0; head = node(0, 0, 0, 0); for (int j = 1; j <= M; ++j) { CH[j] = node(size, size, L[head], head), S[j] = 0; } for (int i = 1; i <= N; ++i) { int row = -1, k; for (int j = 1; j <= M; ++j) { if (mat[i][j] != ILoveMZ) continue; if (row == -1) { row = node(U[CH[j]], CH[j], size, size); RH[row] = i, CH[row] = CH[j], ++S[j]; } else { k = node(U[CH[j]], CH[j], L[row], row); RH[k] = i, CH[k] = CH[j], ++S[j]; } } }}void remove(const int c) { L[R[c]] = L[c], R[L[c]] = R[c]; for (int i = D[c]; i != c; i = D[i]) { for (int j = R[i]; j != i; j = R[j]) { U[D[j]] = U[j], D[U[j]] = D[j]; --S[CH[j]]; } }}void resume(const int c) { for (int i = U[c]; i != c; i = U[i]) { for (int j = L[i]; j != i; j = L[j]) { ++S[CH[j]]; U[D[j]] = D[U[j]] = j; } } L[R[c]] = R[L[c]] = c;}int len;int rname[300][4];int cline , pline;int n , m;int now;int canoc[12347][9];int cntcanoc[12347];bool useCo[9];int cntuseCo;int cntCoNow;bool DLX(const int k) { if (R[head] == head) { len = k - 1; return true; } int s = inf, c; for (int t = R[head]; t != head; t = R[t]) { if (S[t] < s) s = S[t], c = t; } remove(c); for (int i = D[c]; i != c; i = D[i]) { O[k] = RH[i]; for (int j = R[i]; j != i; j = R[j]) { remove(CH[j]); } bool change = useCo[rname[O[k]][1]]; if (!useCo[rname[O[k]][1]]) ++ cntuseCo; useCo[rname[O[k]][1]] = 1; if (n - k - 1>= cntCoNow - cntuseCo && DLX(k + 1)) { return true; } if (!change){ --cntuseCo; useCo[rname[O[k]][1]] = false; } for (int j = L[i]; j != i; j = L[j]) { resume(CH[j]); } } resume(c); return false;}int _;char str[50][50];bool use[50];int pp[50];const int trynumber[] = {31,1,2,3,4,5,12,13,14,15,23,24,25,34,35,45,123,124,125,134,135,145,234,235,245,345,1234,1235,1245,1345,2345,12345};void occupy(int x){ int y = x; cntcanoc[y] = 0; for (;x;x /= 10){ canoc[y][cntcanoc[y]++] = (x % 10); }}void inittable(){ for (int i = 1 ; i <= 31 ; ++i) occupy(trynumber[i]);}bool hasans;int numberWord;void solve(){ scanf("%d%d" , &n , &m); RST(use); for (int i = 0 ; i < n ; ++i){ while(gets(str[i]) , strlen(str[i]) < m); for (int j = 0 ; j < m ; ++j){ if (str[i][j] < 'A' || str[i][j] > 'Z') continue; //if (!use[str[i][j] - 'A']) cout << str[i][j] << endl; use[str[i][j] - 'A'] = 1; } } printf("Case %d:" , ++_); numberWord = 0; for (int i = 0 ; i < 26 ; ++i){ //printf("%c" , use[i]); if (!use[i] && i < n) { printf(" -1\n"); return; } if (i < n)pp[i] = numberWord ++; if (use[i] && i >= n){ printf(" -1\n"); return; } } //cout << numberWord << endl; hasans = 0; for (int T_ = 1 ; T_ <= 31 ; ++T_){ now = trynumber[T_]; if (now % 10 > m) continue; //RST(mat); ++ILoveMZ; cline = 0; int cColumn = 2 * n; cntCoNow = cntcanoc[now]; for (int i = 0 ; i < n ; ++i){ for (int T_T = 0 ; T_T < cntCoNow ; ++T_T){ int j = canoc[now][T_T] - 1; if (str[i][j]< 'A' || str[i][j] > 'Z') continue; ++cline; rname[cline][0] = i; rname[cline][1] = j; mat[cline][pp[str[i][j] - 'A'] + 1] = ILoveMZ; mat[cline][n + i + 1] = ILoveMZ; //printf("%d %d %d\n" , i , j , pp[str[i][j] - 'A'] + 1); } } pline = cline;/* for (int i = 0 ; i < SZ(use) ; ++i){ mat[++pline][i + 1] = 1; }*/ init(pline , cColumn); RST(useCo); cntuseCo = 0; if(DLX(0)){ hasans = 1; printf(" %d" , now); } } if (!hasans) printf(" -1\n"); else{ printf("\n"); }}#define Rush int T____; RD(T____); DO(T____)#define DO(n) for ( int ____n ## __line__ = n; ____n ## __line__ -- ; )int main(){ //freopen("input.txt" , "r" , stdin); //freopen("output.txt" , "w" , stdout); ILoveMZ = 0; RST(mat); _ = 0; inittable(); Rush solve();}
感想:
第一次写这么恶心的题目,不过对于这种题目已经有了自己的心得。有了胆量,有了基友们的支持,终于过掉了此题。感觉很好,调试了奖金7h的题目,终于过掉长舒一口气呢。各位晚安~~~
谢谢妹子孟竹始终给我支持~ILoveYou
- [Liiurujia Birthday Match] Q 调试了将近7h的题目
- 拖了将近一个月的----C++初学之路
- 实习将近两个月了
- python题目-----search()和match()的区别
- 我刚刚写了一个map的题目,还用到了#include<string>的头文件,下面我来总结一下 map<类型>变量 q q.find(找字符串) q.end()是否到达末尾
- 昨天下午到现在,将近一天的时间卡在了cmakelists.txt关键的一句话
- 毛泽东为何抛弃给他当了将近20年秘书的田家英?
- 搞了将近一个月的AS400,现在又转回Android~
- 将近两个点换来的成果
- 工作将近2月了。个人感受
- 将近一年了,很少来更新自己的blog,这几天要多浇浇水了:)
- 题目 H
- 转眼间已在北京工作了将近一个月了
- 今天又去面试了,面试了将近四个小时
- 将近一个月的php学习总结
- 收购 LinkedIn 将近一年后,微软终于动手了
- D-Day +15 of .NET 找到组织了!ohYes~~去学长那里聊了将近1个小时,发现自己学院还是有高人在的!
- SAP ABAP /h Debugging Trick (/ h的调试技巧)
- php 使用cookie判断登录
- [Leetcode] Flatten Binary Tree to Linked List
- 黑马程序员_学习记录20:HTML,JavaScript,CSS小结
- 怎么从ActionInvocation(拦截器)中获取用户jsp表单提交的所有值,比如用户输入的任意项
- [Leetcode] Jump Game
- [Liiurujia Birthday Match] Q 调试了将近7h的题目
- Linux C编程第五回 - 时间函数
- 黑马程序员_学习记录21:高新技术之反射小结
- 黑马程序员_学习记录22:JavaBean
- Struts2源码分析--请求处理(大侠啊 跪拜了)
- [Leetcode] Jump Game II
- [Leetcode] Length of Last Word
- [Leetcode] Generate Parentheses
- LeetCode: Longest Valid Parentheses