牛人自有牛人的做法,弱渣也有弱渣的做法。。。分享一下。。
Problem C. Dijkstra
因为ijk = -1
那么我们只需要找prefix的i和suffix的k即可。
而发现一共就4种运算符,所以最多8位一个循环,那么我就if X > 20 then X = 20
重载了一下运算符号,这样就能避免很多不必要的麻烦写法
昂神教我的,既然是乘法那么正负符号分开算好了。。
char str[1000000];
string L , a;
LL n , x;
int c[][4] = { {0 , 1 , 2 , 3},
{1 , 0 , 3 , 2},
{2 , 3 , 0 , 1},
{3 , 2 , 1 , 0}};
int neg[][4] = {{1 , 1 , 1 , 1},
{1 ,-1 , 1 ,-1},
{1 ,-1 ,-1 , 1},
{1 , 1 ,-1 ,-1}};
int f(char c){
if (c == 'i') return 1;
if (c == 'j') return 2;
return 3;
}
struct Number{
int ele , op;
void ONE(){
ele = 0;
op = 1;
}
Number(){}
Number(int c){
ele = c;
op = 1;
}
Number operator * (const Number & A) const{
Number ret;
ret.op = op * neg[ele][A.ele] * A.op;
ret.ele = c[ele][A.ele];
return ret;
}
};
void solve(){
cin >> n >> x;
a = RS(str);
printf("Case #%d: " , ++Case);
Number pre;
pre.ONE();
for (int i = 0 ; i < n ; ++i){
pre = pre * Number(f(a[i]));
}
Number res;res.ONE();
LL k = x;
while(k)
{
if(k&1) res = res * pre;
pre = pre * pre, k >>= 1;
}
if (res.ele != 0 || res.op != -1){
puts("NO");
return;
}
L = "";
if (x > 20) x = 20;
DO(x) L += a;
int left = -1 , right = -1;
res.ONE();
for (int i = 0 ; i < L.length() ; ++i){
res = res * Number(f(L[i]));
if (res.ele == 1 && res.op == 1){
left = i;
break;
}
}
res.ONE();
for (int i = L.length() - 1 ; i >= 0 ; --i){
res = Number(f(L[i])) * res;
if (res.ele == 3 && res.op == 1){
right = i;
break;
}
}
// cerr << left << ' ' << right << endl;
puts((left != -1 && right != -1 && left < right) ? "YES" : "NO");
}Problem D. Ominous Omino
从来没有枚举对过。所以从一开始就没打算去枚举。。
一看,<=20,打表啊!公司机器跑的飞快!
我一看到题,看到这个图
就知道X>=7肯定无解啊,然后就sb地忘了写了23333.
首先是如何枚举Domino块呢,我们想如果按照X = 1 , 2 , 3 。。。 的顺序枚举的话,那么我们只用在 X -> X + 1 的时候枚举一块在已有的Domino周围转一圈,然后去重即可。(我是按照Left-Top的地方戳齐)
然后就是非常暴力地模拟。。找到每一块,然后枚举放在哪个地方,然后剩下的搜。。
怎么搜呢,可以直接再枚举一遍所有的块所有可以放的位置,然后就是一个Dancing Links X Method里面的精确覆盖问题(数据范围那么小是吧。。。)
搜到X = 6 , R = 4 , C = 18 的时候TMD搜不出来了!!于是发现如果 R * C % X == 0 并且 r <= R , c <= C 的 X , r , c 答案是 GABRIEL 的话,那么 R , C 肯定也是。。方法是——
按照这种放法肯定能放下的吧2333
const int maxM = 25 * 25, maxN = 760 * 6 * 6 + 5;
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++;
}
bool 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]) 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;
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]);
}
if (DLX(k + 1)) {
return true;
}
for (int j = L[i]; j != i; j = L[j]) {
resume(CH[j]);
}
}
resume(c);
return false;
}
int X , RR , CC;
const int DN = 7;
typedef set<PII> :: iterator DITER;
struct Domino{
set<PII> a;
bool operator < (const Domino & A) const{
for(set<PII> :: iterator ia = a.begin() , ib = A.a.begin() ; ia != a.end() && ib != A.a.end() ; ++ia , ++ib){
if ((*ia) > (*ib)) return false;
if ((*ia) < (*ib)) return true;
}
return false;
}
void output(){
for ( DITER i = a.begin() ; i != a.end() ; ++i)
cerr << '(' << i -> fi << ',' << i -> se << ')' << ',';
cerr << endl;
}
Domino rot(){
Domino ret;
ret.a.clear();
PII lt = MP(10 , 10);
for(DITER i = a.begin() ; i != a.end() ; ++i){
checkMin(lt.fi , -i -> se);
checkMin(lt.se , i -> fi);
}
for(DITER i = a.begin() ; i != a.end() ; ++i){
ret.a.insert(MP(- i->se - lt.fi , i->fi - lt.se));
}
return ret;
}
}now;
set<Domino> PSet , DSet , checkList;
void Insert(Domino cur){
PII lt = MP(10 , 10) , nt;
for (DITER iter = cur.a.begin() ; iter != cur.a.end() ; ++iter){
checkMin(lt.fi , iter -> fi);
checkMin(lt.se , iter -> se);
}
for (DITER i = cur.a.begin() ; i != cur.a.end() ; ++i){
for (int d = 0 ; d < 4 ; ++d){
PII g = MP(i -> fi + dx4[d] , i -> se + dy4[d]);
if (cur.a.find(g) != cur.a.end()) continue;
nt = MP(min(lt.fi , g.fi) , min(lt.se , g.se));
Domino add;
add.a.clear();
for ( DITER j = cur.a.begin() ; j != cur.a.end() ; ++j){
add.a.insert(MP(j -> fi - nt.fi , j -> se - nt.se));
}
add.a.insert(MP(g.fi - nt.fi , g.se - nt.se));
DSet.insert(add);
}
}
}
void init(){
if (X == 1){
now.a.clear();
now.a.insert(MP(0 , 0));
DSet.insert(now);
}
else{
PSet = DSet;
DSet.clear();
for (set<Domino> :: iterator iter = PSet.begin() ; iter != PSet.end() ; ++iter)
Insert(*iter);
}
int Count = 0;
for (set<Domino> :: iterator iter = DSet.begin() ; iter != DSet.end() ; ++iter){
Domino e = *iter;
cerr << (++Count) << ":\t";
e.output();
}
}
int A[25][25] , num[25][25];
int line;
bool inmap(int x , int y){
return 0 <= x && x < RR && 0 <= y && y < CC;
}
bool putin(Domino d , int x , int y){
++Case;
for(DITER i = d.a.begin() ; i != d.a.end() ; ++i){
int gx = x + i -> fi , gy = y + i -> se;
if (!inmap(gx , gy)) return false;
A[gx][gy] = Case;
}
int c = 0;
for (int i = 0 ; i < RR ; ++i)
for (int j = 0 ; j < CC ; ++j)
if (A[i][j] != Case)
num[i][j] = ++c;
if (c == 0) return true;
line = 1;
for (int i = 0 ; i < RR ; ++i){
for (int j = 0 ; j < CC ; ++j){
for (set<Domino> :: iterator k = DSet.begin() ; k != DSet.end() ; ++k){
now = *k;
bool ok = true;
RST(mat[line]);
for ( DITER z = now.a.begin() ; ok && z != now.a.end() ; ++z){
int gx = i + z -> fi , gy = j + z -> se;
if (!inmap(gx , gy) || A[gx][gy] == Case){
ok = false;
break;
}
mat[line][num[gx][gy]] = 1;
//cerr << line << ' ' << gx << ' ' << gy << ' ' << num[gx][gy] << endl;
//getchar();
}
if (ok) ++line;
}
}
}
line--;
init(line , RR * CC - X);
if (DLX(0))
return true;
return false;
}
bool canput(Domino d){
if (checkList.find(d) != checkList.end()) return true;
RST(A);
Case = 0;
for (int t = 0 ; t < 4 ; ++t){
checkList.insert(d);
d = d.rot();
}
for (int t = 0 ; t < 4 ; ++t){
for (int i = 0 ; i < RR ; ++i)
for (int j = 0 ; j < CC ; ++j)
if (putin(d , i , j))
return true;
d = d.rot();
}
return false;
}
bool check(){
checkList.clear();
cerr << "CHECK" << ' ' << X << ' ' << RR << ' ' << CC << endl;
for (set<Domino> :: iterator iter = DSet.begin() ; iter != DSet.end() ; ++iter){
if (!canput(*iter)) return true;
}
return false;
}
const int MM = 20;
void solve(){
init();
vector<PII> okSet ;
okSet.clear();
for (RR = 1 ; RR <= MM ; ++RR)
for (CC = RR ; CC <= MM ; ++CC){
if (RR * CC % X != 0 || (RR < X && CC < X)){
cout << "{" << X << ',' << RR << ',' << CC << "},";
cout << "{" << X << ',' << CC << ',' << RR << "},";
cerr << "{" << X << ',' << RR << ',' << CC << "}" << endl;
continue;
}
bool pass = false;
for (int i = 0 ; i < okSet.size() ; ++i)
if (okSet[i].fi <= RR && okSet[i].se <= CC){
pass = true;
continue;
}
if (pass) continue;
if (check()){
cout << "{" << X << ',' << RR << ',' << CC << "},";
cout << "{" << X << ',' << CC << ',' << RR << "},";
cerr << "{" << X << ',' << RR << ',' << CC << "}" << endl;
}
else{
okSet.PB(MP(RR , CC));
}
}
}
本文深入探讨了算法实现和具体技术应用,包括但不限于Dijkstra算法优化、Ominous Omino问题解决策略、字符操作与字符串处理技巧。文章详细阐述了解决方案、核心逻辑与优化方法,旨在为读者提供深入理解与实际应用的指南。
3837

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



