Execution Timed Out - Binary Chess

Buongiorno, ho problemi di Execution Timed Out nel problema binary chess.
Ho applicato una recursion calcolando tutte le possibili combinazioni. Se un rook uccide un bishop o contrario allora ritorno 0. Se arrivo alla fine ritorno 1.
La memoizzazione memorizza le coppie di rook o bishop che non possono stare nella stessa combinazione.
E’ possibile ottimizzare questa risoluzione o devo cambiare metodo?
Grazie in anticipo.

#include <bits/stdc++.h>
using namespace std;

int n;
vector <pair <int, bool>> p[200000][2];

long long int risolvi(bool rb, int i, int x[], int y[], bool v[])
{	
	for(pair<int, bool> e : p[i][rb])				//memoizzazione
	{
		if(v[e.first] == e.second)
			return 0;
	}
   
    v[i] = rb;

    if(rb == 0) //rook
    {
        for(int k = i - 1; k >= 0; k--)
        {  
            if(v[k] == 1)
            {
                if((x[k] == x[i] || y[k] == y[i]))
				{
					p[i][rb].push_back(make_pair(k, v[k]));
					return 0;
				}
                if((abs(x[k] - x[i]) == abs(y[k] - y[i])))
				{
					p[i][rb].push_back(make_pair(k, v[k]));
					return 0;
				}
            }
        }
    }
    else
    {
        for(int k = i - 1; k >= 0; k--)   //alfiere
		{
			if(v[k] == 0)
            {
                if((x[k] == x[i] || y[k] == y[i]))
				{
					p[i][rb].push_back(make_pair(k, v[k]));
					return 0;
				}
                if((abs(x[k] - x[i]) == abs(y[k] - y[i])))
				{
					p[i][rb].push_back(make_pair(k, v[k]));
					return 0;
				}
            }
        }
    }

	if(i >= n-1)
	{
		return 1;
	}

	return (risolvi(0, i+1, x, y, v) + risolvi(1, i+1, x, y, v));
}

int main()
{
	ifstream in("input.txt");
	int r, c;
	in >> r >> c >> n;
	
	int x[n], y[n];
	for(int i = 0; i < n; i++)
	{
		in >> x[i] >> y[i];
	}
	
	bool v[n] = {false};
	long long int a = risolvi(0, 0, x, y, v);
	long long int b = risolvi(1, 0, x, y, v);
	
	long long int ris;
	ris = a+b;
	cout << ris % (long long int)(pow(10, 9) + 7);
	return 0;
}

Обичам те :stuck_out_tongue_winking_eye:
UWU

Credo che il ragionamento di fondo del tuo approccio sia troppo lento purtroppo. Prova a rispondere a questa domanda: se 2 pezzi si vedono (sono sulla stessa riga/colonna/diagonale) allora cosa puoi dire riguardo il loro “tipo”?

Sono entrambi alfieri o entrambi torri.

Esatto, immagino tu abbia notato come il ragionamento possa essere esteso transitivamente. Ossia, dati 3 pezzi a, b, c tali che a e b si vedono e b e c si vedono, anche a e c devono essere dello stesso tipo, a prescindere dal fatto che si vedano o meno. Dopo questa considerazione riesci a trovare un modo per riformulare il problema originale in modo che sia più semplice da risolvere?

1 Mi Piace

Penso di aver capito. Grazie mille

Io avevo già implementato questo ragionamento creando delle zone in cui i pezzi si vedono tra di loro ma non vedono quelli delle altre zone. Il massimo che sono riuscito ad ottenere è stato 30/100 per via del tempo, è un problema di python o c’è una qualche ottimizzazione che non ho trovato?

R, C, N = map(int, input().strip().split())

rr = [0 for i in range(N)]
cc = [0 for i in range(N)]
alr = []  # zone
MOD = 10 ** 9 + 7
lu = 0  # numero di zone
for i in range(N):
    rr[i], cc[i] = map(int, input().strip().split())
    coll = []  # collisioni, ovvero le zone a cui il nuovo pezzo appartiene
    new = [i]  # nuova zona
    for j in range(lu):  # scorro nelle zone
        for h in alr[j]:  # scorro tra i pezzi della zona
            if cc[i] == cc[h] or rr[i] == rr[h] or (abs(rr[h] - rr[i]) == abs(
                    cc[h] - cc[i])):  # se il nuovo pezzo è sulla stessa fila, riga o diagonale
                new += alr[j]
                coll.append(j)
                lu -= 1
                break
    for k in coll[::-1]:
        alr.pop(k)

    alr.append(new)
    lu += 1
    lu %= MOD

print((2**lu%MOD))

Il ragionamento è giusto, ma il modo in cui crei gli insiemi che chiami zone è troppo lento. In particolare, tu confronti ogni pezzo con ogni altro pezzo sulla scacchiera, ottenendo una complessità di O(N^2), devi trovare un modo per farlo in O(NlogN). Conosci algoritmi che ti permettono partendo di N insiemi di unire tali insiemi in maniera veloce (e allo stesso tempo ti permettono di capire a quale insieme appartiene ogni elemento)

Avevo pensato all’ union-find disjoint set, ma non ne sono molto pratico

Hai una buona occasione per fare pratica allora :smiley: Questa è come al solito una buona guida

Grazie mille per l’aiuto, adesso mi ci metto