有一个数列a1,a2,a3...an,每次可以从中任意选三个相邻的数ai-1 ,ai , ai+1 ,进行如下操作(此操作称为“对ai进行操作”)
(ai-1,ai,ai+1)->(ai-1+ai,-ai,ai+ai+1)
给定初始和目标序列,是否能通过以上操作,将初始序列转换成为目标序列?例如,初始序列(1 6 9 4 2 0)目标序列(7 -6 19 2 -6 6)可经过如下操作:
(1 6 9 4 2 0)->( 1 6 13 -4 6 0)->(1 6 13 2 -6 6)->(7 -6 19 2 -6 6)
请你判断给定的初始状态和目标状态,输出Yes(能够转换)或No(不能转换)
2 3 1 2 3 1 3 2 6 1 6 9 4 2 0 7 -6 19 2 -6 6
No Yes
思路:
看似很费解的搜索,实际可利用“守恒定律”轻松解决
参考资料:http://www.cnblogs.com/dongsheng/archive/2013/03/04/2943099.html
其精髓在于:只要两个序列顺序求和,经排序后,元素按位对应相等,他们就能通过操作互达。
例如:1, 2, 3 => 1, 3, 2 这组示例,顺序求和后转换为 1, 3, 6 => 1, 4, 6; 升序排序后显然不能按位对应相等(3 != 4),所以他们不能互达;
再如:1,6, 9, 4, 2, 0 => 7, -6, 19, 2, -6, 6 这组, 顺序求和后转换为 1, 7, 16, 20, 22, 22 => 7, 1, 20, 22, 16, 22; 将其升序排序后恰能按位对应相等,所以他们能够互达。
代码:
#include <iostream> #include <algorithm> #define N 1001 using namespace std; int a[N] = {0}; int b[N] = {0}; int main() { int loop, n, i; cin >> loop; while(loop --){ cin >> n; for(i = 0; i < n; i ++){ cin >> a[i]; a[i] = a[i] + a[i - 1]; } for(i = 0; i < n; i ++){ cin >> b[i]; b[i] = b[i] + b[i - 1]; } sort(a, a + n); sort(b, b + n); /* for(i = 0; i < n; i ++){ if(a[i] != b[i]){ break; } } if(i != n + 1) cout << "NO" << endl; else cout << "Yes" << endl; */ if( equal(a, a + n - 1, b) ) // STL equal() 判断两个数组是否相等 cout << "Yes" << endl; else cout << "No" << endl; } return 0; }
nyoj-109 数列转换 (守恒定律),布布扣,bubuko.com
原文:http://blog.csdn.net/tbl_123/article/details/23619701