完美的代价 c语言,蓝桥杯基础练习 完美的代价
基礎(chǔ)練習(xí) 完美的代價(jià)
問(wèn)題:
問(wèn)題描述
回文串,是一種特殊的字符串,它從左往右讀和從右往左讀是一樣的。小龍龍認(rèn)為回文串才是完美的。現(xiàn)在給你一個(gè)串,它不一定是回文的,請(qǐng)你計(jì)算最少的交換次數(shù)使得該串變成一個(gè)完美的回文串。
交換的定義是:交換兩個(gè)相鄰的字符
例如mamad
第一次交換 ad : mamda
第二次交換 md : madma
第三次交換 ma : madam (回文!完美!)
輸入格式
第一行是一個(gè)整數(shù)N,表示接下來(lái)的字符串的長(zhǎng)度(N <= 8000)
第二行是一個(gè)字符串,長(zhǎng)度為N.只包含小寫(xiě)字母
輸出格式
如果可能,輸出最少的交換次數(shù)。
否則輸出Impossible
樣例輸入
5
mamad
樣例輸出
3
需要了解:
這道題的關(guān)鍵字是貪心算法,去百度了一下貪心算法,簡(jiǎn)單來(lái)說(shuō)就是在對(duì)問(wèn)題求解時(shí),總是做出在當(dāng)前看來(lái)是最好的選擇。也就是說(shuō),不從整體最優(yōu)上加以考慮,他所做出的僅是在某種意義上的局部最優(yōu)解。
在本題中也就是找到能夠與之相匹配的字符。然后,進(jìn)行交換,直至達(dá)到目標(biāo)要求。
題目分析:
首先分析Impossible 的兩種情況
n為奇數(shù)時(shí),如果已經(jīng)有一個(gè)字符出現(xiàn)的次數(shù)為奇數(shù),還找到了一個(gè)字符出現(xiàn)的次數(shù)為奇數(shù),那么就不能構(gòu)成回文串。
n為偶數(shù)時(shí),只要找到有一個(gè)字符出現(xiàn)的次數(shù)為奇數(shù),那么就不能構(gòu)成回文串。
還有一個(gè)就是題目所說(shuō)的最小的交換次數(shù)
如果 n 為偶數(shù),那么從第一字符開(kāi)始,從后往前找第一個(gè)和它相同的字符,如果找了,就將找到的字符交換到最后一個(gè)位置,在下一次遍歷時(shí),就可以不用管剛才已經(jīng)交換好的那來(lái)兩個(gè)字符,下一次從第二個(gè)字符開(kāi)始,從倒數(shù)第二個(gè)字符開(kāi)始遍歷,執(zhí)行和上述相同的操作。
如果 n 為奇數(shù),在字符串的某一個(gè)位置找到了那個(gè)出現(xiàn)次數(shù)為奇數(shù)的字符,我們不必將次字符現(xiàn)在就交換到中間位置,而是先計(jì)算它到中間位置需要交換的次數(shù),然后累加到 count 中,將剩下的字符都交換到對(duì)稱(chēng)后,再交換這個(gè)字符即可。
這是因?yàn)槿绻哑鏀?shù)移動(dòng)到中間,假設(shè)有一對(duì)數(shù)都在以中間為界限的左邊或者都在右邊的話(huà),那么交換成回文的時(shí)候就一定要經(jīng)過(guò)中間,這就會(huì)造成count多增加了一次,這是不必要的,因?yàn)榭梢运械幕匚囊苿?dòng)完了之后再把這個(gè)獨(dú)立的奇數(shù)移動(dòng)過(guò)去,不僅能達(dá)到同樣的效果還能保證交換次數(shù)最少。
例如:
有這么幾個(gè)數(shù)
b d c c f f b
我們不考慮第二個(gè)奇數(shù)直接交換第三個(gè)數(shù),這樣只需要1步,但是當(dāng)你把第二個(gè)奇數(shù)交換到中間之后就會(huì)有如下結(jié)果
b c c d f f b
可以了解一下 φ(>ω
代碼:
#include
#include
using namespace std;
int main() {
int n;
cin >> n;
string s;
cin >> s;
int end = n - 1;//字符串最后一個(gè)字符
int count = 0;//交換次數(shù)
int OddNum = 0;//判斷是否已經(jīng)有一個(gè)單獨(dú)的奇?zhèn)€數(shù)的字符了
for (int i = 0; i < end; ++i) {//從第一個(gè)字符到倒數(shù)第二個(gè)字符遍歷
for (int j = end; j >= i; --j) {//從最后一個(gè)開(kāi)始,到第i個(gè)字符,尋找與s[i]相同的字符
if (i == j) {//如果沒(méi)找到
if (n % 2 == 0 || OddNum == 1) { //不可能的兩種情況
cout << "Impossible" << endl;
return 0;
}
OddNum = 1;//找到一個(gè)字符出現(xiàn)的次數(shù)為奇數(shù)
count += n / 2 - i;//將次字符交換到中間位置的次數(shù)
}
else if (s[i] == s[j]) {//如果找到了,將s[j]交換到s[end]位置
for (int k = j; k < end; ++k) {
swap(s[k], s[k + 1]);//交換相鄰兩個(gè)位置的字符
++count;
}
--end;//末尾遞減
break; //開(kāi)始從i+1處重復(fù)操作
}
}
}
cout << count << endl;
system("pause");
return 0;
}
對(duì)于我:
但是在這里我還發(fā)現(xiàn)我有一個(gè)基礎(chǔ)知識(shí)點(diǎn)薄弱的地方那就是多個(gè)if跟if··· if else 的區(qū)別
if (條件){語(yǔ)句}
這種格式中,程序會(huì)依次判斷條件1和條件2是否成立并根據(jù)結(jié)果決定是否執(zhí)行語(yǔ)句1和語(yǔ)句2,也就是說(shuō),第一個(gè) if 塊和第二個(gè) if 塊沒(méi)有影響(除非在執(zhí)行第一個(gè) if 塊的時(shí)候就兇殘地 return 了)
而下面這種格式,
if (條件){}
else if(條件){}
f 塊和 else if 塊本質(zhì)上是互斥的!也就是說(shuō),一旦語(yǔ)句1得到了執(zhí)行,程序會(huì)跳過(guò) else if 塊,else if 塊中的判斷語(yǔ)句以及語(yǔ)句2一定會(huì)被跳過(guò);同時(shí)語(yǔ)句2的執(zhí)行也暗含了條件1判斷失敗和語(yǔ)句1沒(méi)有執(zhí)行;當(dāng)然還有第3個(gè)情況,就是條件1和條件2都判斷失敗,語(yǔ)句1和語(yǔ)句2都沒(méi)有得到執(zhí)行。
總結(jié)
以上是生活随笔為你收集整理的完美的代价 c语言,蓝桥杯基础练习 完美的代价的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2017c语言考核册答案,2017年最新
- 下一篇: 编码互换变量c语言,【剑仙教程】TC。字