2022.6.8———HZOI【2022高考集训3】游寄

写在前面

这回我用了【奇技淫巧】

我倒序开题哈哈哈哈

因为我看最后一题顺眼bushi

还是成绩综述的啦

WR果然AK了!!巨佬%%%%%%%%%%%%%%%%

初一大佬jijidawang顺手来机房A了三道题爆踩我!太巨了!!

zcyzcy和闫仁里Sakura也好巨!

kkkzuto发挥稳定太强啦!!

Kaguya不愧是蓬莱山公主(bushi

dbx巨巨巨!gtm大牛!smtwy好SMART!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

我一个大傻蛋就是逊啦qAq

T1 Watching Fireworks is Fun

一道单调队列优化dp

(怎么老是dp

滚动数组优化一下空间

具体看我代码吧()()

里面有个地方不知道为啥这么写,先咕掉

T1
/*#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#define ll long long
#define re register int
#define char_phi signed
#define _MARK printf("###");
#define MARK "###"
#define SLEEP "💤"
#define STAR "⭐"
#define _ " "
#define Endl putchar('\n')
#define MIN(x,y) ((x < y) ? (x) : (y))
#define MAX(x,y) ((x > y) ? (x) : (y))
#define N 150005
#define M 305
#define T 1000000005
using namespace std;
ll n, m, d, RRR, RT;
ll final_ans(-200506285201314);
struct boom{
    ll a, b, t;
}f[N];
struct node{
    ll w[100];
};
map<ll,node> mp;
inline ll read(){
    ll x(0); char c;
    while(!isdigit(c = getchar()));
    do{
        x = (x << 3) + (x << 1) + (c & 15);
    }while(isdigit(c = getchar()));
    return x;
}
ll dfs(ll x, ll t, ll rp){
    // cout << SLEEP << t << endl;
    // cout << STAR << rp << endl;
    // cout << x << endl;
    if(mp[t].w[0] != 0){//要放烟花
        for(re i = 1 ; i <= mp[t].w[0] ; ++ i){
            rp += (f[mp[t].w[i]].b - abs(f[mp[t].w[i]].a - x));
        }
        // cout << STAR << rp << endl;
    }
    if(t == RT){
        return rp;
    }
    ll res1(-1145141919810), res2(-1145141919810);
    //往左边走
    if(x >= d+1) res1 = dfs(x-d, t+1, rp);
    //往右边走
    if(x <= (RRR-d)) res2 = dfs(x+d, t+1, rp);
    //我记得题目没说可以不动吧?
    return (MAX(res1, res2));
}
void work(){
    /*
    话说很久没有看过烟花了呜
    ————————————————————————————————————————————
    多重背包裸题吧?我昨天中午还看了
    但是我还是没有看懂。。更别提应用了
    所以这道题怎么做呢?
    Source:
    让(Ai-x)尽量趋近0,也就是让自己尽量靠近烟花燃放的地点(不怕闪到眼么())
    作为一个蒟蒻,我肯定是不会背包的了啦
    从1~n枚举起点x,然后直接暴搜,每个地方要决定一下往那边走,我肯定是两边都枚举一下啦
    然后标记一下在每个时间有哪些烟花放了,用map映射一下,因为二维数组太逊了啦开不下
    话说用map会不会MLE
    递归边界: t == max_of_ti  烟花数量也行,殊途同归

    ——————————————————————————————————————————
    话说起点可以二分不(不行吧?)
    */
    //两个样例都过了...希望别爆零
    /*n = read(), m = read(), d = read();
    for(re i = 1 ; i <= m ; ++ i){
        f[i].a = read(), f[i].b = read(), f[i].t = read();
        mp[f[i].t].w[++ mp[f[i].t].w[0]] = i, RRR = MAX(RRR, f[i].a), RT = MAX(RT, f[i].t);
    }
    cout << SLEEP << RRR << _ << RT << endl;
    for(re i = 1, reser ; i <= RRR ; ++ i){
        // _MARK;
        reser = dfs(i, 1, 0);//////
        final_ans = MAX(final_ans, reser);
    }
    cout << final_ans;
}
char_phi main(){
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    work();
    return 0;
}*/
//仍然是重构奥
#include <iostream>
#include <cstdio>
using namespace std;
#define char_phi signed
#define re register int
#define ll long long
#define STAR "⭐"
#define SLEEP "💤"
#define MARK printf("###")
#define _MARK "###"
#define ABS(x) (((x) < 0) ? (-(x)) : (x))
#define MIN(x,y) ((x < y) ? (x) : (y))
#define MAX(x,y) ((x > y) ? (x) : (y))
#define N 150005
using namespace std;
ll n, m, d, k, lst, t, a, b, dis, l, r, final_ans;
ll q[N<<1];
ll f[2][N];
inline ll read(){
    ll x(0); char c;
    while(!isdigit(c = getchar()));
    do{
        x = (x << 3) + (x << 1) + (c & 15);
    }while(isdigit(c = getchar()));
    return x;
}
void work(){
    n = read(), m = read(), d = read();
    lst = 1;
    for(re charphi(1) ; charphi <= m ; ++ charphi){
        a = read(), b = read(), t = read();
        dis = MIN(n, d*(t-lst));//从上一次烟花到这一次烟花最多能走多远
        lst = t;//See you Next time...
        k ^= 1;//滚动array
        l = 1, r = 1;
        for(re i(1), j(1) ; i <= n ; ++ i){//i是枚举当前烟花
            for( ; j <= (i+dis) && j <= n ; ++ j){//j是上一次烟花我可能在的位置
                while(l < r && f[k^1][j] >= f[k^1][q[r-1]]){//为啥>=、>都行
                    //上一次j位置的最优值比队尾大那就更新队尾
                    r--;
                }
                q[r] = j, ++ r;
            }
            while(l < r && q[l] < i - dis){//保证队头范围
                ++ l;
            }
            f[k][i] = f[k^1][q[l]] + b-ABS(a-i);//nnngt!!!ABS都能写挂
        }
    }
    final_ans = -200506285201314;
    for(re i(1) ; i <= n ; ++ i){
        final_ans = MAX(final_ans, f[k][i]);
    }
    cout << final_ans;
}
char_phi main(){
    freopen("fire.in","r",stdin);
    freopen("fire.out","w",stdout);
    work();
    return 0;
}

T2 Perform巡回演出

又一个dp

就是读入有点恶心人

怎么做去看冬天雨姐姐的题解吧~我就只给代码了(实际上是我中午没睡觉太累了嗷

T2
//额?各位都改的这么快阿。。。
//改题不用特别着急吧?改题更重要的是理解。。


/*#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#include <cstring>
#define ll long long
#define re register int
#define char_phi signed
#define _MARK printf("###");
#define MARK "###"
#define SLEEP "💤"
#define STAR "⭐"
#define _ " "
#define Endl putchar('\n')
#define MIN(x,y) ((x < y) ? (x) : (y))
#define MAX(x,y) ((x > y) ? (x) : (y))
#define N 15
using namespace std;
int n, k, star_cnt, final_ans;
// int head[N<<2];
// map<int,int> mp;
// struct star{
//     int v, w, nxt;
// }e[N<<2];
inline int read(){
    int x(0); char c;
    while(!isdigit(c = getchar()));
    do{
        x = (x << 3) + (x << 1) + (c & 15);
    }while(isdigit(c = getchar()));
    return x;
}
/*
inline void star_add(int u,int v, int w, int t){
    e[++ star_cnt].v = v, e[star_cnt].w = w, e[star_cnt].nxt = head[u], head[u] = star_cnt;
    mp[t] = star_cnt;
}
int dfs(int x, int t, int res){
    if(t == k){
        if(x != n){
            return 114514191;
        }
        else {
            return res;
        }
    }
    int rs(0);
    for(re i = head[x],reser(0) ; i ; i = e[i].nxt){
        reser = dfs(e[i].v, t+1, res+e[mp[t]].w);
        rs = MIN(rs, reser);
    }
    return res+rs;
}*/
/*void work(){
    /*
    记得memset!
    康了康题目,这输入格式真真的难读懂
    这个题应该是最短路 但是我还是太逊了
    嗯 先去一趟厕所想一想
    嗯...这个题,又得深搜
    */
/*    while(1){
        n = read(), k = read();
            // _MARK;
        if(n == 0 && k == 0){
            exit(0);
        }
        // memset(head, 0, sizeof(head)), memset(e, 0, sizeof(e)), star_cnt = 0;
        for(re i = 1, uu, vv ; i <= n ; ++ i){//每个城市
            // uu = i;
            for(re j = 1,ww,d ; j <= n-1 ; ++ j){//到另外的城市
                d = read();
                // if(j == i) ++ j;//()()
                // vv = j;
                // cout << SLEEP << d << endl;
                for(re oi = 1 ; oi <= d ; ++ oi){
                    ww = read();
                    // for(re kk = oi ; kk <= k ; kk += d){//。。这建边可真恶心啊
                    //     star_add(uu,vv,ww,kk);//建边建错了,淦
                    // }
                }
            }
        }
        // final_ans = dfs(1, 1, 0);
        // cout << final_ans << endl;
        //好像是没时间了的说
        //没时间了,骗分(虽然不可能骗到的啦)
        if(n == 3 && k == 6){
            puts("460");
            continue;
        }
        puts("0");
    }
}
char_phi main(){
    freopen("perform.in", "r", stdin);
    freopen("perform.out", "w", stdout);
    work();
    return 0;
}*/
//依旧是重构一波{
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define ll long long
    #define re register int
    #define char_phi signed
    #define _MARK printf("###");
    #define MARK "###"
    #define SLEEP "💤"
    #define STAR "⭐"
    #define _ " "
    #define Endl putchar('\n')
    #define MIN(x,y) ((x < y) ? (x) : (y))
    #define MAX(x,y) ((x > y) ? (x) : (y))
    #define N 15
    #define K 1005
//}
using namespace std;
int n, k, tmper;
int f[K][N];//f[i][j] 第i天从1到j点的最优方案
int pl[N][N][K];
inline int read(){
    int x(0); char c;
    while(!isdigit(c = getchar()));
    do{
        x = (x << 3) + (x << 1) + (c & 15);
    }while(isdigit(c = getchar()));
    return x;
}
void work(){
    /*
    感觉出题人不会描述读入,这描述了个啥啊,我读了二十分钟差评dd
    */
    while(true){
        n = read(), k = read();
        if(n == 0 && k == 0){
            exit(0);
        }
        memset(f,0x3f,sizeof(f));
        tmper = f[1][1];
        for(re i = 1 ; i <= n ; ++ i){
            for(re j = 1, d ; j <= n ; ++ j){
                if(i == j) continue;
                d = read();
                for(re w = 1 ; w <= d ; ++ w){
                    pl[i][j][w] = read();
                }
                for(re w = d+1 ; w <= k ; ++ w){
                    pl[i][j][w] = pl[i][j][w-d];//哇塞冬天雨姐姐的高明之处,像我那么整的就🙅‍
                    //不愧是鸣鸣0阿
                }
            }
        }
        for(re i = 2 ; i <= n ; ++ i){//从1到每个城市
            if(pl[1][i][1] != 0){//有直达航班
                f[1][i] = pl[1][i][1];//初始化
            }
        }
        for(re i = 2 ; i <= k ; ++ i){//everyday
            for(re j = 1 ; j <= n ; ++ j){//到哪个点
                for(re w = 1 ; w <= n ; ++ w){//中转站
                    if(j == w || pl[w][j][i] == 0) continue;
                    f[i][j] = MIN(f[i][j], f[i-1][w] + pl[w][j][i]);//和Floyd差不多
                }
            }
        }
        ((f[k][n] == tmper) ? (puts("0")) : (printf("%d\n",f[k][n])));
    }
}
char_phi main(){
    freopen("perform.in","r",stdin);
    freopen("perform.out","w",stdout);
    work();
    return 0;
}

T3 枪战Maf

考试的时候意识到了事情的严重性

链我不会分析nm

所以我就tarjan搞了一下奇环偶环输出,希望他能给个全是环的测试的

结果没给 爆0

Source:

我们不记录死亡人数,记录存活人数

那么这道题中,任何的图有以下三种基本图:

图一:一个纯环

这个图的最大存活人数是size ÷ 2(手模)

最小是一个

图二:一个环带偶数链

先抛开那个偶链,在这个中最大存活人数是size ÷ 2

最小应该是一个,然而有偶链的存在,他注定不平凡

偶链的存在,导致3处于一种可死可不死的状态

如果开枪顺序得当,比如5把4枪掉,6把5枪掉...3把8枪掉,2把3枪掉

那这个环里就没有人活着了 最小存活人数为0

当然了偶链上那个入度为0的一定活

图三:一个环带奇链

这种情况下算最小存活人数是可以把2枪掉的,为0,但是算最大存活人数时可以被7枪掉,为size ÷ 2

你叨叨了这么多,有啥用?你怎么找到一个统一的解法?

额,要来了嘛

明确一个重要的事实:本题只可能存在纯环或者链+环  因为如果是链最后一个点得有个出边吧(题目要求),你指向谁?最后都得是这两种形式

对图三整个以及图二的链跑一个类似广搜板子的东西(可以用队列也可以不用)

从入度为0的点也就是不会被枪的点开始搜,他指向的一定死,他指向的指向入度肯定就要-1了

然后他指向的指向属于一种薛定谔猫猫的状态,可以死也可以不死,取决于指向它的人的开枪顺序,这时候把这种人记录一下叫做被救了,同时最大存活++,因为是"最大存活"

然后记得记录一定被枪的并且已经被枪过的就不要跑他了,因为这个我搞了半天


这时候图中只有环了  因为所有的链已经被我们处理过了


对图二的环跑另一个循环,找到一个又没被枪入度又不是0的,那他就属于一个环

对这个环进行遍历。如果这个环遍历的过程中发现有一个点,他被救了,那就说明:

是图二的环。这个环里的最小存活会变成0

没找到?那就是图1的,森林嘛,最小存活人数++


这两个跑完就ok了,记得问的是死亡人数,用n减一下,注意一下输出顺序这个题就做完啦

T3

/*#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define ll long long
#define re register int
#define char_phi signed
#define _MARK printf("###");
#define MARK "###"
#define SLEEP "💤"
#define STAR "⭐"
#define _ " "
#define Endl putchar('\n')
#define MIN(x,y) ((x < y) ? (x) : (y))
#define MAX(x,y) ((x > y) ? (x) : (y))
#define N 1000005
using namespace std;
int n, star_cnt, tarjan_id, strong_num, top, toper, final_ans_of_min, final_ans_of_max;
bool in[N];
int head[N<<1], dfn[N], low[N], belong[N], s[N], siz[N];
struct star{
    int v,nxt;
}e[N<<1];
inline int read(){
    int x(0); char c;
    while(!isdigit(c = getchar()));
    do{
        x = (x << 3) + (x << 1) + (c & 15);
    }while(isdigit(c = getchar()));
    return x;
}
inline void star_add(int u,int v){
    e[++ star_cnt].v = v, e[star_cnt].nxt = head[u], head[u] = star_cnt;
}
void tarjan(int x){
    dfn[x] = low[x] = ++ tarjan_id;
    s[++ top] = x, in[x] = true;
    for(re i = head[x] ; i ; i = e[i].nxt){
        if(dfn[e[i].v] == 0){
            tarjan(e[i].v);
            low[x] = MIN(low[x],low[e[i].v]);
        }
        else if(in[e[i].v] == true){
            low[x] = MIN(low[x],dfn[e[i].v]);
        }
    }
    if(dfn[x] == low[x]){
        ++ strong_num;
        do{
            toper = s[top], top --, in[toper] = false;
            belong[toper] = strong_num, ++ siz[strong_num];
        }while(toper != x);
    }
}
void work(){
    /*T3:{
        感觉多少还是比较水的...
        吗?
        首先题目很清晰银杏地把自环的可能告诉我们了
        然后画出来样例,是个带环的森林
        然后就分析出了一些性质:
        对于环:{
            对于偶环:
                至多有(size[i] - 1)个殇
                至少有(size[i]/2)个殇
            对于奇环:
                至多有(size[i] - 1)个殇
                至少有(ceil((size[i]/2)))个殇
        }
        别的没想出来呢,大概是拓扑序一类
        所以我现在去三楼推推柿子
        20min later——
        我回来了,基本上啥都没推出来
        这玩意让我隐隐约约想到最小生成树...
        乱图:最多的殇有几个的话,应该是有入度的就会成殇
        但是...最少?
        不知道,很不知道
        甚至最多这个结论也有点牵强,毕竟是枚举来的
        Source:
        只能赌一把数据点中有全是环的那种
        直接跑tarjan。奇环偶环搞一下输出得了
    }*/
/*    n = read();
    for(re i = 1,vv ; i <= n ; ++ i){
        vv = read();
        star_add(i, vv);
    }
    for(re i = 1 ; i <= n ; ++ i){
        if(dfn[i] == 0){
            tarjan(i);
        }
    }
    // cout << SLEEP << strong_num << endl;
    for(re i = 1 ; i <= strong_num ; ++ i){//跑全是环的话没问题 希望不会爆0
        if((siz[i] & 1) == 0){//偶环
            // _MARK;
            // cout << siz[i] << endl;
            final_ans_of_min += (siz[i] >> 1);
            final_ans_of_max += (siz[i] - 1);
        }
        else {
            final_ans_of_min += ceil(siz[i]/2.0);
            final_ans_of_max += (siz[i] - 1);
        }
    }
    cout << final_ans_of_min << _ << final_ans_of_max ;
}
char_phi main(){
    freopen("maf.in","r",stdin);
    freopen("maf.out","w",stdout);
    work();
    return 0;
}*/
//A very interesting 题 that very exercise your 思维
// {
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #define ll long long
    #define re register int
    #define char_phi signed
    #define PIGEON "🕊"
    #define pigeon true
    #define _MARK printf("###");
    #define MARK "###"
    #define SLEEP "💤"
    #define STAR "⭐"
    #define _ " "
    #define Endl putchar('\n')
    #define MIN(x,y) ((x < y) ? (x) : (y))
    #define MAX(x,y) ((x > y) ? (x) : (y))
    #define N 1000005
    using namespace std;
// }
int n, mxalive, mnalive;//记录活的是因为记录死的还要判奇环偶环(好像),麻烦(其实也麻烦不了多少)
bool dead[N], save[N];
int direct[N], ru[N], cp[N];
// int l(1), r, q[N];
inline int read(){
    int x(0); char c;
    while(!isdigit(c = getchar()));
    do{
        x = (x << 3) + (x << 1) + (c & 15);
    }while(isdigit(c = getchar()));
    return x;
}
void work(){
    /*
    不是,就没人想用tarjan?
    没错!这道题,我都不用!
    */
    /*
    不愧是smartWY,讲的真好!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    只有三种基本图
    一:纯环
    二:环上带奇数链
    三:环上带偶数链
    第一个循环处理情况三还有情况2中的奇链
    第二个循环处理情况二的环和情况一
    */
    //?WA成30?mnalive爆了
    n = read();
    for(re i = 1 ; i <= n ; ++ i){
        direct[i] = read();
        ++ ru[direct[i]];
    }
    for(re i = 1 ; i <= n ; ++ i){
        if(ru[i] == 0){
            cp[++ cp[0]] = i;//入度为0的点,他指向的一定死,记录
            ++ mxalive, ++ mnalive;
        }
    }
    //处理图三以及图二中的链
    int now;
    while(cp[0] != 0){
        now = cp[cp[0]];
        -- cp[0];
        if(dead[direct[now]] == true) continue;//果然像王一说的一样,太细了阿。。。
        dead[direct[now]] = true, save[direct[direct[now]]] = true;
        -- ru[direct[direct[now]]];//画图模一下
        if(ru[direct[direct[now]]] == 0){
            ++ mxalive;
            cp[++ cp[0]] = direct[direct[now]];
        }
    }
    /*while(l <= r){
        now = q[l];
        ++ l;
        if(dead[direct[now]] == true) continue;
        dead[direct[now]] = true;
        ru[direct[direct[now]]] --;
        save[direct[direct[now]]] = true;
        if(ru[direct[direct[now]]] == 0){
            ++ mxalive;
            q[++ r] = direct[direct[now]];
        }
    }*/
    //此时只有环力
    //处理图一以及图二中的环
    bool fl(false); int huannum(0);
    for(re i = 1 ; i <= n ; ++ i){
        if(dead[i] == false && ru[i] != 0){
            fl = false, huannum = 0, now = i;
            while(pigeon){//环内循环
                if(dead[now] == true){
                    break;
                }
                if(save[now] == true){
                    fl = true;//是图二的环
                }
                ++ huannum;
                dead[now] = true;
                now = direct[now];
            }
            if(fl == false && huannum > 1){//不是自环,而且是环1
                ++ mnalive;
            }
            mxalive += (huannum >> 1);
        }
    }
    cout << (n-mxalive) << _ << (n-mnalive);
}
char_phi main(){
    freopen("maf.in","r",stdin);
    freopen("maf.out","w",stdout);
    work();
    return 0;
}

T4 翻转游戏

霍!赛时先开的这个题

这道题我看其他人都写得挺麻烦的,还有状压的

就我一个人想暴搜?

应该不是,但我这个暴搜写麻烦了所以别具一格...

我的代码就作为个参考吧,我写了一堆不必要(应该是)的特判,估计你也不想看下去

思路:把输入的b,w看作1,0,递归暴力枚举每一个点是否使用魔法,这是个庞大的搜索树,可以枚举出所有的情况,所以就放心打吧

时间复杂度是Θ(2pos),pos是点的个数,本题只有16个点,216 = 65536所以完全能跑过

T4

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <ctime>
#define ll long long
#define re register int
#define char_phi signed
#define MARK "###"
#define SLEEP "💤"
#define STAR "⭐"
#define _ " "
#define Endl putchar('\n')
#define MIN(x,y) ((x < y) ? (x) : (y))
#define MAX(x,y) ((x > y) ? (x) : (y))
#define N 8
using namespace std;
int final_ans;
int a[N][N], kl[N][N];
/*inline void backer(){
    for(re i = 1 ; i <= 4 ; ++ i){
        for(re j = 1 ; j <= 4 ; ++ j){
            kl[i][j] = a[i][j];
        }
    }
}*/
int qwq;
inline bool check(){
    qwq = kl[1][1];
    for(re i = 1 ; i <= 4 ; ++ i){
        for(re j = 1 ; j <= 4 ; ++ j){
            if(kl[i][j] != qwq){
                return false;
            }
        }
    }
    return true;
}
// 0 0 0 0
// 0 0 0 0
// 0 0 0 0
// 0 0 0 0
// 1 1 1 1
// 1 1 1 1
// 1 1 1 1
// 1 1 1 1
int dfs(int x, int y, int t){
    // now = clock();
    // if(now - fst >= 900){/////////////////////////////////////////////
    //     puts("Impossible");//这喝鸡汤,十分滴美味
    //     exit(0);
    // }
    if(x == 4 && y == 4){
        if(check() == true){
            return t;
        }
        /*cout << SLEEP << t << endl;
        cout << STAR; Endl;
        cout << "{" << x << "," << y << "}" << endl;
        for(re i = 1 ; i <= 4 ; ++ i){
    	    for(re j = 1 ; j <= 4 ; ++ j){
                cout << kl[i][j] << _;
		    }
            Endl;
        }*/
        kl[4][4] ^= 1, kl[3][4] ^= 1, kl[4][3] ^= 1;
        // cout << STAR; Endl;
        /*Endl;
        // cout << "{" << x << "," << y << "}" << endl;
        for(re i = 1 ; i <= 4 ; ++ i){
    	    for(re j = 1 ; j <= 4 ; ++ j){
                cout << kl[i][j] << _;
		    }
            Endl;
        }
        cout << STAR;Endl,Endl;*/
        if(check() == true){
            kl[4][4] ^= 1, kl[3][4] ^= 1, kl[4][3] ^= 1;
            // MARK;
            
            return t+1;
        }
        // else return -1;
        else {
            kl[4][4] ^= 1, kl[3][4] ^= 1, kl[4][3] ^= 1;
            return 11451419;
        }
    }
    if(check() == true){
        // cout << SLEEP << t << endl;
        return t;
    }
    // cout << STAR; Endl;
    // cout << "{" << x << "," << y << "}" << endl;
    // for(re i = 1 ; i <= 4 ; ++ i){
    // 	for(re j = 1 ; j <= 4 ; ++ j){
    //         cout << kl[i][j] << _;
	// 	}
    //     Endl;
	// }
    // cout << STAR;Endl,Endl;
    int res1, res2;
    if(x == 1 && y == 1){
        MARK;
        kl[1][1] ^= 1, kl[1][2] ^= 1, kl[2][1] ^= 1;//翻
        res1 = dfs(x, y+1, t+1);
        kl[1][1] ^= 1, kl[1][2] ^= 1, kl[2][1] ^= 1;//不翻
        res2 = dfs(x, y+1, t);
    }
    else if(x == 1 && y == 2){
        kl[1][1] ^= 1, kl[1][2] ^= 1, kl[1][3] ^= 1, kl[2][2] ^= 1;
        res1 = dfs(x, y+1, t+1);
        kl[1][1] ^= 1, kl[1][2] ^= 1, kl[1][3] ^= 1, kl[2][2] ^= 1;
        res2 = dfs(x, y+1, t);
    }
    else if(x == 1 && y == 3){
        kl[1][2] ^= 1, kl[1][3] ^= 1, kl[1][4] ^= 1, kl[2][3] ^= 1;
        res1 = dfs(x, y+1, t+1);
        kl[1][2] ^= 1, kl[1][3] ^= 1, kl[1][4] ^= 1, kl[2][3] ^= 1;
        res2 = dfs(x, y+1, t);
    }
    else if(x == 1 && y == 4){
        kl[1][4] ^= 1, kl[1][3] ^= 1, kl[2][4] ^= 1;
        res1 = dfs(2, 1, t+1);
        kl[1][4] ^= 1, kl[1][3] ^= 1, kl[2][4] ^= 1;
        res2 = dfs(2, 1, t);
    }
    else if(x == 2 && y == 1){
        kl[2][1] ^= 1, kl[1][1] ^= 1, kl[2][2] ^= 1, kl[3][1] ^= 1;
        res1 = dfs(x, y+1, t+1);
        kl[2][1] ^= 1, kl[1][1] ^= 1, kl[2][2] ^= 1, kl[3][1] ^= 1;
        res2 = dfs(x, y+1, t);
    }
    else if(x == 2 && y == 4){
        kl[2][4] ^= 1, kl[1][4] ^= 1, kl[2][3] ^= 1, kl[3][4] ^= 1;
        res1 = dfs(3, 1, t+1);
        kl[2][4] ^= 1, kl[1][4] ^= 1, kl[2][3] ^= 1, kl[3][4] ^= 1;
        res2 = dfs(3, 1, t);
    }
    else if(x == 3 && y == 1){
        kl[3][1] ^= 1, kl[2][1] ^= 1, kl[4][1] ^= 1, kl[3][2] ^= 1;
        res1 = dfs(x, y+1, t+1);
        kl[3][1] ^= 1, kl[2][1] ^= 1, kl[4][1] ^= 1, kl[3][2] ^= 1;
        res2 = dfs(x, y+1, t);
    }
    else if(x == 3 && y == 4){
        kl[3][4] ^= 1, kl[2][4] ^= 1, kl[3][3] ^= 1, kl[4][4] ^= 1;
        res1 = dfs(4, 1, t+1);
        kl[3][4] ^= 1, kl[2][4] ^= 1, kl[3][3] ^= 1, kl[4][4] ^= 1;
        res2 = dfs(4, 1, t);
    }
    else if(x == 4 && y == 1){
        kl[3][1] ^= 1, kl[4][2] ^= 1, kl[4][1] ^= 1;
        res1 = dfs(x, y+1, t+1);
        kl[3][1] ^= 1, kl[4][2] ^= 1, kl[4][1] ^= 1;
        res2 = dfs(x, y+1, t);
    }
    else if(x == 4 && y == 2){
        kl[4][2] ^= 1, kl[4][1] ^= 1, kl[4][3] ^= 1, kl[3][2] ^= 1;
        res1 = dfs(x, y+1, t+1);
        kl[4][2] ^= 1, kl[4][1] ^= 1, kl[4][3] ^= 1, kl[3][2] ^= 1;
        res2 = dfs(x, y+1, t);
    }
    else if(x == 4 && y == 3){
        kl[4][3] ^= 1, kl[4][2] ^= 1, kl[4][4] ^= 1, kl[3][3] ^= 1;
        res1 = dfs(x, y+1, t+1);
        kl[4][3] ^= 1, kl[4][2] ^= 1, kl[4][4] ^= 1, kl[3][3] ^= 1;
        res2 = dfs(x, y+1, t);
    }
    else{
        kl[x][y] ^= 1, kl[x][y+1] ^= 1, kl[x][y-1] ^= 1, kl[x+1][y] ^= 1, kl[x-1][y] ^= 1;
        res1 = dfs(x, y+1, t+1);
        kl[x][y] ^= 1, kl[x][y+1] ^= 1, kl[x][y-1] ^= 1, kl[x+1][y] ^= 1, kl[x-1][y] ^= 1;
        res2 = dfs(x, y+1, t);
    }
    return (MIN(res1, res2));
}
void work(){
    //范围好小,只有4???
    //暴搜应该完全可以的吧?
    //除非是Θ((n^2)!),别的都跑得过去
    char phi[5];
    for(re i = 1 ; i <= 4 ; ++ i){
        scanf("%s",phi+1);
        for(re j = 1 ; j <= 4 ; ++ j){
            (phi[j] == 'b') ? (a[i][j] = kl[i][j] = 1) : (a[i][j] = kl[i][j] = 0);
        }
    }
    /*for(re i = 1 ; i <= 4 ; ++ i){
        for(re j = 1 ; j <= 4 ; ++ j){
            cout << kl[i][j] << _;
        }
        Endl;
    }*/
    final_ans = dfs(1,1,0);
    if(final_ans == 11451419){
        goto CHAR_PHI;
    }
    printf("%d",final_ans);
    // now = clock();
    // cout << endl << endl << now << _ << fst << endl;
    //呜呜,呜呜呜,蒟蒻的大暴搜竟然过样例了呜呜呜呜呜
    /*
    我焯吓死我了我焯,把自己hack了
    幸亏我又找了出来,吓坏我了
    /*是这个:
wbww
bbbw
wbwb
wwbb
    */
    // if(final_ans == -1){
    //     goto CHAR_PHI;
    // }
    //暴搜打不出来,准备骗分
    //这个题可以打表。但是暴力打不出来
    /*if(a[1][1] == 1 && a[1][2] == 0 && a[1][3] == 0 && a[1][4] == 1){
        if(a[2][1] == 1 && a[2][2] == 1 && a[2][3] == 0 && a[2][4] == 1){
            if(a[3][1] == 1 && a[3][2] == 0 && a[3][3] == 0 && a[3][4] == 1){
                if(a[4][1] == 1 && a[4][2] == 0 && a[4][3] == 0 && a[4][4] == 0){
                    puts("4");
                    exit(0);
                }
            }
        }
    }
    final_ans = a[1][1];
    for(re i = 1 ; i <= 4 ; ++ i){
        for(re j = 1 ; j <= 4 ; ++ j){
            if(a[i][j] != final_ans){
                goto CHAR_PHI;
            }
        }
    }
    puts("0");*/
    return;
    CHAR_PHI:{
        puts("Impossible");
        exit(0);
    }
}
char_phi main(){
    // fst = clock();
    freopen("flip.in","r",stdin);
    freopen("flip.out","w",stdout);
    work();
    return 0;
}

唉,这四天多的集训就要结束啦,收获不少呢

更加期待暑假集训啦!

然而,同样重要的是,后天期末考试!

期末加油!!!

posted @   char_phi  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示