2020ICPC上海 B.Mine Sweeper II(思維,亂搞)

tomjobs發表於2020-12-17

題意:
掃雷,給你A,B圖。權值為所有非雷點的和,要求你修改B圖中不超過(n*m/2)個點,使得A,B圖權值相等。

思路:
感覺過的太多了,肯定不難。模擬發現,每個點變化值1,2,3,4…都有,所以大膽猜測一定有解,所以直接用優先佇列存下修改每個點造成的權值變化,然後每次取出最大(最小)的,來逼急差值,使得A,B儘可能相等。再更新周圍8個點。

寫的很噁心了。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 7;
char a[maxn][maxn],b[maxn][maxn];
int val[maxn][maxn],vis[maxn][maxn];
int dirx[] = {0,0,0,1,1,1,-1,-1,-1};
int diry[] = {0,1,-1,0,1,-1,0,1,-1};
int n,m;
struct Node { //mx
    int x,y,v;
    int id;
    bool operator < (const Node&rhs) const {
        if(v == rhs.v && id == rhs.id) return x + y < rhs.x + rhs.y;
        return v < rhs.v;
    }
};

struct Node2 { //mi
    int x,y,v;
    int id;
    bool operator < (const Node2&rhs) const {
        if(v == rhs.v && id == rhs.id) return x + y < rhs.x + rhs.y;
        return v > rhs.v;
    }
};

void Print() {
    for(int i = 1;i <= n;i++) {
        for(int j = 1;j <= m;j++) {
            printf("%c",b[i][j]);
        }
        printf("\n");
    }
}

priority_queue<Node>q;
priority_queue<Node2>q2;
void change(int x,int y,int flag) {
    if(b[x][y] == '.') {
        b[x][y] = 'X';
    } else {
        b[x][y] = '.';
    }
    int cnt = 0;
    for(int d = 1;d <= 8;d++) {
        int dx = x + dirx[d],dy = y + diry[d];
        if(dx <= 0 || dy <= 0 || dx > n || dy > m) continue;
        vis[dx][dy]++;
        if(b[x][y] == b[dx][dy]) {
            cnt++;
            val[dx][dy] += 2;
        } else {
            cnt--;
            val[dx][dy] -= 2;
        }
        if(!flag) {
            q.push({dx, dy, val[dx][dy], vis[dx][dy]});
        } else {
            q2.push({dx, dy, val[dx][dy], vis[dx][dy]});
        }
    }
    val[x][y] = cnt;

    if(!flag) {
        q.push({x,y,val[x][y],vis[x][y]});
    } else {
        q2.push({x,y,val[x][y],vis[x][y]});
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++){
        scanf("%s",a[i] + 1);
    }
    for(int i = 1;i <= n;i++) {
        scanf("%s",b[i] + 1);
    }
    int suma = 0,sumb = 0;
    for(int i = 1;i <= n;i++) {
        for(int j = 1;j <= m;j++) {
            if(a[i][j] == 'X') continue;
            int cnt = 0;
            for(int d = 1;d <= 8;d++) {
                int dx = i + dirx[d],dy = j + diry[d];
                if(dx <= 0 || dy <= 0 || dx > n || dy > m) continue;
                if(a[dx][dy] == 'X') cnt++;
            }
            suma += cnt;
        }
    }
    int mine = 0;
    for(int i = 1;i <= n;i++) {
        for(int j = 1;j <= m;j++) {
            if(b[i][j] == 'X') {
                mine++;
            }
            int cnt = 0,cnt2 = 0;
            for(int d = 1;d <= 8;d++) {
                int dx = i + dirx[d],dy = j + diry[d];
                if(dx <= 0 || dy <= 0 || dx > n || dy > m) continue;
                if(b[dx][dy] == 'X') cnt++;
                if(b[i][j] == b[dx][dy]) {
                    cnt2++;
                } else {
                    cnt2--;
                }
            }
            if(b[i][j] == '.') {
                sumb += cnt;
            }
            val[i][j] = cnt2;
            q.push({i,j,cnt2,0});
            q2.push({i,j,cnt2,0});
        }
    }
    if(suma == 0) {
        for(int i = 1;i <= n;i++) {
            for(int j = 1;j <= m;j++) {
                if(b[i][j] == 'X' && mine <= n * m / 2) {
                    b[i][j] = '.';
                } else if(b[i][j] == '.' && mine > n * m / 2) {
                    b[i][j] = 'X';
                }
            }
        }

    } else {
        int T = n * m * 2;
        while(T) {
            if(T <= 0 || suma == sumb) break;
            if(sumb < suma) {
                Node now = q.top();q.pop();
                if(now.id < vis[now.x][now.y]) continue;
                if(sumb + now.v <= suma) {
                    T--;
                    sumb += now.v;
                    change(now.x,now.y,0);
                }
            } else {
                Node2 now = q2.top();q2.pop();
                if(now.id < vis[now.x][now.y]) continue;
                if(sumb + now.v >= suma) {
                    T--;
                    sumb += now.v;
                    change(now.x,now.y,1);
                }
            }
        }
    }
    if(sumb == suma || suma == 0) Print();
    else printf("-1\n");
    return 0;
}

相關文章