1. 程式人生 > 實用技巧 >題解 CF508B 【Anton and currency you all know】

題解 CF508B 【Anton and currency you all know】

這道題是一道還算可以的貪心,我們考慮的貪心思路是

  1. 把最靠近最後一位的偶數與最後一位交換,反例: 12345應該變為15342,而此時的變化為12354.排除。
  2. 把位於高位且比最後一位(L-1)的數小的數和最後一位交換, 例如 2455->5352. 但顯然這樣寫的程式碼是錯誤的,會存在最後一個數比所有的偶數都小,舉個反例 4443->4434而不是3444.也排除。
  3. 先從高位到低位遍歷一遍,找到第一個比最後一位小的偶數即可,如果不存在,就再從後往前遍歷一遍,找到最低位的偶數與最後一位交換即可。
    (這是正解!)
  4. 記得特判一下全是奇數,沒有偶數的情況,直接輸出-1即可。

(本人較菜,所以用了字串轉陣列,在數組裡進行的操作)

for(int i=0;i<l;i++) 
    {
        a[i]=s[i]-'0';//轉數字 
        if(a[i]%2==0)
        {
            ok=1;//檢視是否有偶數 
        }
    }
//大體的操作就是這樣,在數組裡面做運算就不用考慮忘記刪掉'0'的問
//題,但是這樣的空間可能會佔用的大一些

程式碼詳解:利用flag和ok兩個bool變數,一個記錄是否有偶數,一個去尋找最高位的偶數,在去利用變數q去存最高位的偶數的下標,便於交換
AC程式碼如下:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#define maxn 100005
#define ll long long
#define itn int
#define INF 1e+9
using namespace std;
string s;//存初始的串 
int a[maxn],q;//a[]表示轉換後的數字串 
bool flag=0,ok=0; 
int main()
{
    cin>>s; 
    int l=s.length();
    memset(a,0,sizeof(a));
    for(int i=0;i<l;i++) 
    {
        a[i]=s[i]-'0';//轉數字 
        if(a[i]%2==0)
        {
            ok=1;//檢視是否有偶數 
        }
    }
    for(int i=0;i<l;i++)
    {
        if(a[i]%2==0&&flag==0&&a[i]<a[l-1])//找到在最高(所有偶數中位置最靠前)位且比最後一位小的偶數 
        {
            flag=1;
            q=i;
            continue;   
        }
    }
    if(ok==0)//全是奇數 
    {kaoqian
        printf("-1\n");
        return 0;
    }
    if(flag==1) 
        swap(a[q],a[l-1]);
    else //不存在比最後一位小的偶數 
    {
        for(int i=l-1;i>=0;i--)//找到最靠後的一位偶數 
        {
            if(a[i]%2==0)
            {
                swap(a[i],a[l-1]);
                break;
            }
        }
    }
    for(int i=0;i<l;i++)//正序輸出 
    {
        printf("%d",a[i]);
    }
}