CF1120B Once in a casino

CF1120B Once in a casino

洛谷传送门

题目大意

给定两个长度都为n(1leq nleq 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(1leq lleq n-1,s=pm 1)d**i,s**i(1≤ln−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
",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
",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;
}
原文地址:https://www.cnblogs.com/fusiwei/p/14044323.html