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≤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\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;
}
posted @ 2020-11-26 20:23  Seaway-Fu  阅读(95)  评论(0编辑  收藏  举报