hdu4876 深搜+(随机枚举剪枝)
生活随笔
收集整理的這篇文章主要介紹了
hdu4876 深搜+(随机枚举剪枝)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題意:
? ? ? 給你n個(gè)數(shù),讓你從選擇k個(gè)數(shù),然后排成一個(gè)環(huán)(k個(gè)數(shù)的順序隨意,但是排成一個(gè)環(huán)后就不能變了),然后可以在這個(gè)環(huán)上任意的找連續(xù)w個(gè)數(shù)(w<=k),可以找多次,得到一個(gè)值等于當(dāng)前找的連續(xù)的數(shù)的異或和,最后問(wèn)你能找到>=L&&<=R的最大的R,L,R之間的數(shù)必須全部存在,給你N,K,L,求最大的R.
思路:
? ? ? 給你n個(gè)數(shù),讓你從選擇k個(gè)數(shù),然后排成一個(gè)環(huán)(k個(gè)數(shù)的順序隨意,但是排成一個(gè)環(huán)后就不能變了),然后可以在這個(gè)環(huán)上任意的找連續(xù)w個(gè)數(shù)(w<=k),可以找多次,得到一個(gè)值等于當(dāng)前找的連續(xù)的數(shù)的異或和,最后問(wèn)你能找到>=L&&<=R的最大的R,L,R之間的數(shù)必須全部存在,給你N,K,L,求最大的R.
思路:
? ? ? 直接先暴力找到k個(gè)數(shù)(最多C(20,6)),然后在枚舉這k個(gè)數(shù)的全排列(全排列有STL函數(shù),不想用可以自己深搜枚舉),對(duì)于每一個(gè)序列求出所有可能解,找到最大的R,更新答案,這里有一個(gè)很重要的剪枝,也是這個(gè)題目的核心就是在全排列之前可以先判斷一下是否可能存在可以更新R的最優(yōu)解,直接深搜枚舉當(dāng)前這k個(gè)數(shù)(不用管順序,是找可能存在),看看組成的最大的是否比當(dāng)前的最大R大,如果不是,那么就沒必要全排列再去枚舉了,時(shí)間復(fù)雜度 深搜判斷是 O(2^5) 而直接來(lái)全排列+枚舉是 O(5! * 5 * 5),題目說(shuō)的是隨機(jī)數(shù)據(jù),所以不存在那種全是極端數(shù)據(jù),也就是所有情況都滿足的數(shù)據(jù),所以相比之下,還是加上那個(gè)剪枝比較合算。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std;int N ,K ,L ,R ,ks; int num[25] ,mark[130]; int now[25];void mk_jude(int k ,int sum) {if(k == K + 1) return ;mark[sum ^ now[k]] = 1;mk_jude(k + 1 ,sum ^ now[k]);mk_jude(k + 1 ,sum); }int jude(int k ,int sum) {memset(mark ,0 ,sizeof(mark));mk_jude(1 ,0);for(int i = L ;i <= R ;i ++)if(!mark[i]) return 0;return 1; }void dfs(int k ,int I) {if(k == K + 1){ if(!jude(1 ,0)) return;int tmp[25];for(int i = 1 ;i <= K ;i ++)tmp[i] = now[i];for(int tt = 1 ;tt <= ks ;tt ++){memset(mark ,0 ,sizeof(mark));for(int i = 1 ;i <= K ;i ++){int sum = 0;for(int j = 1 ;j <= K ;j ++){int a = i + j - 1;if(a > K) a -= K;sum = sum ^ tmp[a];mark[sum] = 1;}} int mk = 0;for(int i = L ;1 ;i ++)if(!mark[i]){mk = i - 1;break; } if(R < mk) R = mk;next_permutation(tmp + 1 ,tmp + K + 1);}return ;}if(I == N + 1) return;now[k] = num[I];dfs(k + 1 ,I + 1);dfs(k ,I + 1); }int main () {int i;while(~scanf("%d %d %d" ,&N ,&K ,&L)){for(i = 1 ;i <= N ;i ++)scanf("%d" ,&num[i]);for(R = 0 ,ks = 1 ,i = 2 ;i <= K ;i ++)ks *= i;dfs(1 ,1);if(R < L) R = 0;printf("%d\n" ,R);}return 0; }
總結(jié)
以上是生活随笔為你收集整理的hdu4876 深搜+(随机枚举剪枝)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: hdu4882 水贪心
- 下一篇: hdu4771 水搜索(状态压缩+bfs