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.此外...