P2962(折半搜尋 狀壓)

2021-10-08 02:16:02 字數 1780 閱讀 5926

題目

挺新奇的一題,用二進位制對應位來表示是第幾個燈,同時也用二進位制來表示對燈的操作,將和這個燈相連的那些燈全部置一,其他置零,那麼我們對某個燈進行操作就只需要和這個燈相異或。比如,0號燈和1,3兩個燈相連,二進位制表示出來就是00…0001011,由於和1相異或狀態取反,和0相異或狀態不變,我們如果改變了第0個燈的狀態,那麼1、3也會改變,而把二進位制表示的狀態和00…0001011相異或就可以得到改變0號燈狀態後的狀態。此外,這個題直接搜尋對所有燈的操作與否複雜度會有2^35,會超時,所以採用折半搜尋,先對前面一半的燈進行操作,並用map儲存達到的狀態及其對應的操作次數,然後對後面一半進行操作,更新答案。

值得一提的是,每個燈最多隻需要操作一次,因為對乙個燈操作兩次就會變回原來的狀態,既然要最少那不如不操作。

//#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define lson (rt << 1)

#define rson (rt << 1 | 1)

#define lowbit(x) ((x)&(-x))

const

int maxn =

1000+10

;const

int maxm =

2000+10

;const

int inf_max =

0x3f3f3f

;const

int mod =

1000000007

;const

double eps =

1e-4

;using

namespace std;

typedef

long

long ll;

inline

intread()

while

(ch>=

'0'&& ch<=

'9') x = x*

10+ ch -

'0',ch =

getchar()

;return x*f;

}mapint>f;

ll a[40]

;int

main()

for(

int i =

0;i <(1

<<

(n/2))

;++i)}if

(!f.

count

(s)) f[s]

= cnt;

else f[s]

=min

(f[s]

,cnt)

;//如果這個狀態存在,肯定取操作次數少的

}int ans =50;

for(

int i =

0;i <(1

<<

(n-n/2)

);++i)

}//後半部分的狀態是s,按照題意s的二進位制後n-n/2位全部為1,和目標狀態相異或後就可以得到前n/2個應該有的狀態

//如果這個狀態用前半部分的操作可以得到,那麼我們更新答案;

if(f.

count((

(1ll

<)^s)

) ans =

min(ans,cnt+f[((

1ll<)^s]);

} cout

}

24,折半查詢

include 折半查詢 二分查詢又稱折半查詢,優點是比較次數少,查詢速度快,平均效能好 其缺點是要求待查表為有序表,且插入刪除困難。因此,折半查詢方法適用於不經常變動而查詢頻繁的有序列表。首先,假設表中元素是按公升序排列,將表中間位置記錄的關鍵字與查詢關鍵字比較,如果兩者相等,則查詢成功 否則利用...

6 2 2 折半查詢

折半查詢,又稱二分查詢,它適用於有序的順序表。基本思路是 首先將給定值key與表中中間位置元素的關鍵字比較,若相等,則查詢成功,返回該元素的儲存位置 若不等,則所需查詢的元素只能在中間元素以外的前半部分或後半部分中 例如,在查詢表公升序排列時,若給定值key大於中間元素的關鍵字,則所查詢的元素只可能...

6 13 折半查詢

給乙個嚴格遞增數列,函式int search bin sstable t,keytype k 用來二分地查詢k在數列中的位置。函式介面定義 int search bin sstable t,keytype k 其中t是有序表,k是查詢的值。裁判測試程式樣例 include using namespa...