\(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,表示...