a数组变成b数组

题目描述:
给出两个元素数量相等的数组,一个a数组,一个b数组,你可以从a数组中任意选择一个数(ai)- 1,一个数(aj)+1。目标是将a数组变成b数组。操作次数不限制。

输入:

第一行:T个测试样例(T <= 100)

第二行:数组的元素数量(N <= 100)

第三行:a数组

第四行:b数组

输出:

若对a数组怎么操作也不能变成b数组,则输出-1(有解);

若有解,则输出路径;

样例:

输入:

4
4
1 2 3 4
3 1 2 4
2
1 3
2 1
1
0
0
5
4 3 2 1 0
0 1 2 3 4

输出:

2
2 1
3 1
-1
0
6
1 4
1 4
1 5
1 5
2 5
2 5

注解:

对于第一个样例:(下标是从1开始的)

i=2, j=1: [1,2,3,4]→[2,1,3,4];

i=3, j=1: [2,1,3,4]→[3,1,2,4];

思路:

首先,先判断有没有解,因为是每次操作是选定两个元素,一个元素减1,一个元素加1,所以说有解的话,a中每个元素与b中对应的每个元素的差值(a[i] - b[i])的和应该为0,只有这样才能保证有解。

我们把a中每个元素和b中对应的元素的差值存到数组里,这样容易确定对a中哪个元素进行哪个操作:

若差值为正数,说明a的元素比b中对应元素大,那么a中的对应元素(ai)肯定要 -1;若差值为负数,说明a的元素比b中对应元素小,那么a中的对应元素(aj)要 + 1。

由于我们需要输出路径(a中哪个元素怎么变的),所以我们要找到某种方法来确保每一组输出的路径合理且正确。这种通法就是遍历c数组(操作次数就是差值为正数(或者负数)的个数,正数负数相抵消),第一个差值为整数的c[i]对应的a[i],让它-1,并用一个变量记录当前的i;第一个差值为负数的的c[i]对应的a[i] ,让它+1,,并用另一个变量记录当前的i。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include <map>

using namespace std;

const int N = 1e2 + 10;

int a[N],b[N],c[N]; // c数组记录差值 
int cnt; // 记录操作次数 
int sum; // 判断有没有解 

int main()
{
    int t;
	scanf("%d",&t);
	
	while(t --)
	{
		sum = 0;
		cnt = 0;
		int n;
		scanf("%d",&n);
		
		for(int i = 1 ; i <= n ; i ++)  scanf("%d",&a[i]);
		for(int i = 1 ; i <= n ; i ++)  scanf("%d",&b[i]); 
		
		//初始化c数组 
		for(int i = 1 ; i <= n ; i ++)  c[i] = a[i] - b[i];
		
		
		for(int i = 1 ; i <= n ; i ++)  sum += c[i];
		
		if(sum != 0)
		{
			printf("-1\n");
		}
		else
		{
			//求操作次数 
		    for(int i = 1 ; i <= n ; i ++)
		    {
			    if(c[i] > 0)  cnt += c[i];
		    }
		    printf("%d\n",cnt);
		    
	        int l,r; // 记录动态的i,j值方便输出路径 
		    for(int k = 1 ; k <= cnt ; k ++)
		    {
			    for(int i = 1 ; i <= n ; i ++)
		        {
			        if(c[i] > 0)
		     	    {
				       l = i;
				       a[i] --;
				       c[i] --;
				       break; 
			        }
		        }
		    
		        for(int i = 1 ; i <= n ; i ++)
		        {
			        if(c[i] < 0)
			        {
				       r = i;
				       a[i] ++;
				       c[i] ++;
				       break;
			        }
	            } 
	            printf("%d %d\n",l,r);
		    }
		}
	} 
	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

21RGHLY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值