反轉(開關問題)

2021-10-24 16:17:43 字數 1836 閱讀 2950

poj3276

n頭牛排成一列,牛頭向前或向後。擁有一台自動轉向機器,設定數值k,每次使用可以令k頭連續的牛轉向。求為了讓所有的牛都面向前方需要的最少操作次數m和對應最小的k。

首先交換區間順序對結果是沒有影響的,此外對同乙個區間進行兩次以上反轉是多餘的。因此,問題轉化成了求需要被反轉的區間的集合。於是先考慮最左端的牛,包含這頭牛的區間只有乙個,若這頭牛面朝後方,對應的區間就必須反轉,此後這個最左的區間也不用再考慮了。這樣通過首先考慮最左端的牛,問題的規模縮小了1,不斷重複就可以無需搜尋求出最少所需反轉次數。

維護區間反轉的部分複雜度降為(n

2n^2

n2)m[i]:區間[i,i+k-1]進行反轉則為1,否則為0.

#include

#include

#include

#include

using namespace std;

int f

[6000];

int m

[6000];

//記錄區間[i,i+k-1]是否反轉

int n;

int calc

(int k)

sum+=

m[i];if

(i-k>=

0)sum-=

m[i-k+1]

;}for(int i=n-k+

2;i<=n;i++

)return res;

}int main()

int k=1

,m=n;for

(int k=

1;k<=n;k++)}

printf

("%d %d",k

,m);

}

poj3279

有n×

\times

×m個格仔,每格可以反轉正反面,一面黑一面白,最終要使所有格仔都反轉成白色,每次反轉時與它上下左右鄰接的格仔也會反轉,求最少翻轉次數,最小步數多個解時,輸出字典序最小一組,解不存在輸出impossible.

首先同乙個格仔翻轉多次是多餘的。先看看左上角的格仔,在這裡除了反轉(1,1)外,反轉(1,2)和(2,1)也可以將這個格仔反轉,所以像上題直接確定的方法行不通。

於是不妨先指定好最上面一行的反轉方法,此時能反轉(1,1)的就只剩(2,1)了,所以只需判斷(2,1)是否需要反轉,如此反覆下去就可以確定所有各自的判斷方法。最後(n,1)~(n,m)如果並非全為白色,就意味著當前不存在可行的操作方法。

這個演算法最上面一行的反轉方式共有2

n2^n

2n種,複雜度為o(mn2

n2^n

2n).

#include

#include

#include

#include

using namespace std;

int m[18

][18]

;//記錄原始情況

int f[18

][18]

;//記錄反轉情況

int a[18

][18]

;//記錄最優情況

const int dx[5]

=;const int dy[5]

=;int n,m;

int get

(int x,int y)

return a%2;

}int calc()

int main()

}if(ans<0)

printf

("impossible\n");

else

}

反轉 開關問題 挑戰程式設計競賽

例題2例題3 農場主約翰把他的 n 1 n 5,000 頭奶牛排成一排,很多都是面向前方的,就像好奶牛一樣。然而,有些人是面向過去的,而他需要所有人都面向未來,以使他的生活變得完美。幸運的是,fj最近買了一台自動翻牛機。因為他購買的是折扣型,所以必須一次性轉 k 1 k n 頭,且只能轉排在一起的奶...

poj3276 反轉 開關問題

題目大意 給你乙個長度為n的字串,包含字母f和b 你可以把區間k 乙個常數 內的所有f變成b,b變成f。為了把這個字串都變成f,求變化的最小次數和其對應的k的值 分析 挑戰程式設計競賽 反轉法的例題,此做法非書上做法 列舉k,對於每個k,只要序列最左端的b變成f,然後依次變化,得到答案 列舉起點然後...

常用技巧精選 反轉(開關問題)

例.給定乙個01串,現有翻轉規則 翻轉某乙個位置時其後面2個位置也會跟著翻轉,也就是每次翻轉都會翻轉3個連續的位置。要將01串全部翻轉為0,求最小的翻轉次數 形似這類題的問題叫做翻轉問題,也可以叫開關問題,對於這類題通常有以下的特點,思考一下就可以想到。1.交換區間得反轉順序隊結果沒有影響。2.此外...