GDOI2016模擬8 21新數獨

2021-07-04 18:21:36 字數 1724 閱讀 4441

題目

下面是乙個沒有數字,只有大小關係(沒錯!那些尖角都是「大於」符號!)的數獨:

除了大小關係外(注意相鄰格仔不能相同),還需要滿足通常的數獨規則:

l 每個格仔都是1~9 的數字

l 每行都是1~9的排列

l 每列都是1~9的排列

l 每個3*3的子矩陣(上圖中用粗線隔開,一共有3*3個這樣的子矩陣)都是1~9的排列

為了美觀,每個3*3子矩陣的所有12對相鄰格仔的大小關係都將給出。

這道題,我們可以注意到有樸素數獨的限制,例如每行都是1~9的排列

, 每列都是1~9的排列,但光有這個,搜尋還是很慢。

那些大於小於號,假設我們現在要確定9要放**,那麼畫出來的圖,對應9的位置,所有符號都是它指向外面的(就是它周圍的都是他指向外面的大於號),這簡直是9在大吼著:「我在這裡…」…於是我就順從了..

對於這個發現,我們可以從大到小列舉先放哪些數,放完9個位置後再放其他的,若存在a<b,則b連a一條邊,並將a入度+1。由於我們每次放的都是現存最大的數,那麼我們按小九宮格為單位,每個九宮格裡找到入度為0的位置,將數填進去,然後消除該位置對周圍位置的影響(類似拓撲排序,將它連出去的位置入度-1)。

加上這個優化,我們就可以飛快的跑過了….(說實話,剛提交**,連running都沒有看到..)

好了,我們來討論一下為甚麼這個剪枝這麼強力?

由於保證存在唯一解,對於相同決策,即同乙個數(指乙個小九宮格內)能填的位置(入度為0)的地方不會超過5,而當你選擇了乙個位置填入的時候,說明你周圍的位置都是先前不可能決策到的(這個可以證明前者),而當前存在多個決策時,則說明以後的決策會少那麼多(我們可以想著乙個正向決策即由大取到小,乙個反向決策即由小取到大)【而且加上數獨的限制,均攤相同決策不超過3個】均攤下來,若要跑得最慢的話,最大決策層在中間,只會有3個相同決策,其餘兩端決策數會依次遞減,均攤69

(我估計的,這也可以接受)而實際上非常小,通常由於唯一解,第一次就會直接搜到答案。

貼**

#include

#include

#include

#define n 10

using namespace std;

intin[82],g[82],a[1000][2],d[82],help[n],b[n];

bool bzh[9][9],bzz[9][9];

void ins(int x,int y)

void did1(int x)

x++;

}}void did2(int x)

}void init()

}int did(int x)

bool jian(int x,int y)

void change(int x,int y)

void changeback(int x,int y)

bool dfs(int x,int y)

if (!y)return

1; s=help[x];

++x;

for (int i=1;i<=9;i++)

if (!d[s+b[i]]&&jian(y,s+b[i])&&!in[s+b[i]])

return0;}

void work()

void write()

}int main()

GDOI2016模擬8 21新Nim遊戲

題目 傳統的nim遊戲是這樣的 有一些火柴堆,每堆都有若干根火柴 不同堆的火柴數量可以不同 兩個遊戲者輪流操作,每次可以選乙個火柴堆拿走若干根火柴。可以只拿一根,也可以拿走整堆火柴,但不能同時從超過一堆火柴中拿。拿走最後一根火柴的遊戲者勝利。本題的遊戲稍微有些不同 在第乙個回合中,第乙個遊戲者可以直...

GDOI2016模擬8 14數樹數

題目 給定一棵n 個節點的樹,標號從1 n。每個點有乙個權值。要求維護兩種操作 1.c i x 0 x 2 31 表示將i 點權值變為x 2.q i j x 0 x 2 31 表示詢問i 到j 的路徑上有多少個值為x 的節點 時間複雜度 n q log n q 2 空間複雜度 n q log n q...

GDOI2016模擬8 8旋轉

alice和bob發明了乙個新的旋轉遊戲。首先,bob給定n個數組成的序列,並把該序列平均分配成若干個塊,每塊正好包含k個數 k能整除n 第一塊由第1到第k個數構成,第二塊由第k 1個數到第2k個數構成,以此類推。接著,bob要求alice對這個序列進行一系列操作,操作有以下兩種 1.把每塊裡面的數...