CF1120B Once in a casino
CF1120B Once in a casino
题目大意
给定两个长度都为n(1\leq n\leq 105)(1≤*n*≤105)的数字串A和B,你可以执行若干次操作,每次操作是将相邻的两个位置+1或-1,要求不能对数字串以外的位置进行操作,且操作中每个数字都必须在[0,9][0,9]中。求把A变成B所执行的最小操作数c,并输出前\min(c,105)min(c,105)个操作,无解输出-1。
输入格式
第一行一个正整数n表示A和B的长度。
接下来有两行,每行一个长度为n的数字串表示A和B。
输出格式
如果不可能把A变成B,输出-1。
否则第一行输出最小操作数c。
接下来输出num=\min(c,10^5)num=min(c,105)行,表示前num个操作,第 i 行输出两个整数d_i,s_i(1\leq l\leq n-1,s=\pm 1)d**i,s**i(1≤l≤n−1,s=±1),表示第 i 个操作将a_{d_i}adi和a_{d_i+1}adi+1加上s_is**i。
题解:
题目大意:给两个数字串,每次可以对\(a[i],a[i+1]\)同时+1或-1,那么请回答能否经过若干次操作使得\(a\)变成\(b\)。如果不能输出\(-1\)。如果能输出最小方案(前\(10^5\)步)。
分析题目,可以发现的性质是:每一位一定受前面那位的影响,所以对前面的数做完修改,在对后面的数做修改时,要考虑好前一次修改的基础。即如果对\(a[i]\)修改了\(b1-a1\),对\(a[i+1]\)要做\(b2-a2-(b1-a1)\)的修改。
然后因为不能超限,所以如果\(a[n]\)也有值的话就说明不能到达。
然后方案就从前往后扫描,对于不合法位置直接dfs输出方案即可。
代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int maxn=1e6+6;
int n;
char s[maxn],t[maxn];
ll ans,a[maxn];
void dfs(int x, int w)
{
if(s[x+1]+w<'0'||s[x+1]+w>'9')
dfs(x+1,-w);
printf("%d %d\n",x,w);
s[x]+=w;
s[x+1]+=w;
if(!(--ans))
exit(0);
}
int main()
{
scanf("%d%s%s",&n,s+1,t+1);
for(int i=1;i<=n;i++)
{
a[i]=-a[i-1]+t[i]-s[i];
ans+=abs(a[i]);
}
if(a[n])
{
puts("-1");
return 0;
}
printf("%lld\n",ans);
if(!ans)
return 0;
ans=min(ans,(ll)1e5);
for(int i=1;i<n;i++)
while(s[i]!=t[i])
dfs(i,t[i]>s[i]?1:-1);
return 0;
}