日常訓練 翻轉硬幣

2022-05-31 04:36:10 字數 1535 閱讀 9725

\(n\)枚硬幣正面朝上擺成一排,給定\(a[1],a[2],…,a[m]\),每次操作可以翻轉連續\(a[i]\)個硬幣.要求經過最少次數的操作,使得僅第\(x[1],x[2],…,x[k]\)枚硬幣反面朝上,輸出最少次數.

第一行三個整數\(n,k,m\).

第二行\(k\)個整數表示需要反面朝上的硬幣位置,從\(1\)編號.

第三行\(m\)個整數表示\(a[1],a[2],…,a[m]\).

乙個整數表示答案,若無解,則輸出\(-1\).

10 8 2

1 2 3 5 6 7 8 9

3 5

2
\(1\;\leq\;n\;\leq\;10^4,1\;\leq\;k\;\leq\;10,1\;\leq\;m\;\leq\;100,1\;\leq\;a[i]\;\leq\;n\).

因為每次翻轉改變的是相鄰兩個硬幣之間的相對狀態.

所以用\(b[i]\)表示相鄰兩個硬幣之間的相對狀態(\(0\):狀態相同;\(1\)狀態不同).

初始狀態和終止狀態便可知了,現在要將終止狀態還原回初始狀態.

每當翻轉\([x+1,x+a[i]]\)(長度為\(a[i]\))時,只對\(b[x],b[x+a[i]]\)產生影響.

當\(b[x]=b[x+a[i]]=0\)時,操作劣.

當\(b[x]=b[x+a[i]]=1\)時,可消掉兩個元素.

當\(b[x]=0,b[x+a[i]]=1\)時,相當於\(x+a[i]\)移動到\(x\).

所以先預處理出每個\(b[i]=1\)的\(i\)到其他\(b[j]=1\)的\(j\)的距離\(g[i][j]\),狀壓\(dp\)即可.

\(f[i]\)為到達狀態\(i\)(二進位製表狀態)所需最少步數.

因為每個元素早消晚消都得消,而且順序沒影響,

所以設\(k\)為使得\(i\&(1\)

<<\(k)=1\)最大的\(k\),

則\(f[i-(1\)

<<\(j)-(1\)

<<\(k)]=min(f[i]+g[j][k])(i\&(1\)

<<\(j)=1,j\;\not=\;k)\).

#include#include#include#include#include#include#include#include#include#include#define k 25

#define m 105

#define n 10005

#define f 1048576

#define inf 20000000

using namespace std;

typedef long long ll;

int g[k][k],f[f],a[m],p[k],dis[n],n,m,k,cnt=-1;

bool b[n];

queueq;

inline void bfs(int u)

if(f[0]else puts("-1");

}int main()

luogu1146 硬幣翻轉

時空限制 1000ms 128mb 在桌面上有一排硬幣,共n枚,每一枚硬幣均為正面朝上。現在要把所有的硬幣翻轉成反面朝上,規則是每次可翻轉任意n 1枚硬幣 正面向上的被翻轉為反面向上,反之亦然 求乙個最短的操作序列 將每次翻轉n 1枚硬幣成為一次操作 輸入格式 輸入只有一行,包含乙個自然數n n為不...

luogu2708 硬幣翻轉

時空限制 1000ms 128mb 難度係數 如果你看懂了 從前有很多個硬幣擺在一行,有正面朝上的,也有背面朝上的。正面朝上的用1表示,背面朝上的用0表示。現在要求從這行的第乙個硬幣開始,將n個硬幣 1 n 硬幣個數 一起翻面,問如果要將所有硬幣翻到正面朝上,最少要進行這樣的操作多少次?輸入格式 乙...

洛谷1146 硬幣翻轉

在桌面上有一排硬幣,共nn枚,每一枚硬幣均為正面朝上。現在要把所有的硬幣翻轉成反面朝上,規則是每次可翻轉任意n 1n 1枚硬幣 正面向上的被翻轉為反面向上,反之亦然 求乙個最短的操作序列 將每次翻轉n 1枚硬幣成為一次操作 乙個自然數nn nn為不大於100100的偶數 第一行包含乙個整數ss,表示...