一.题目链接:
ZOJ-3180
二.题目大意:
六个数 a,b,c,x,y,z.
每次可进行一次操作,选择一个数,赋值为剩下的两个数相加 - 1.
问是否可以将 x,y,z 转变为 a,b,c. (无序)
三.分析:
正推的话会炸掉.
如果逆推,注意操作的特点.
假设 a,b,c 升序
易得 c == a + b - 1.
则可得上一状态为 a,b, b - a - 1.
网上一些其他的 AC 代码貌似没有考虑全情况,居然过了!woccccc,这么暴力都可以!!!orzzz
比如当 x,y,z 为(1 1 1)或(0 0 0)时会无限循环下去,这里要特判一下.
四.代码实现:
#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define eps 1e-6
#define PI acos(-1.0)
#define ll long long int
using namespace std;
int a[3];
int b[3];
int c[3][3];
bool check()
{
for(int i = 0; i < 3; ++i)
{
bool flag = 1;
for(int j = 0; j < 3; ++j)
{
if(a[j] != c[i][j])
{
flag = 0;
break;
}
}
if(flag)
return 1;
}
return 0;
}
bool fun()
{
bool flag;
sort(a, a + 3);
sort(b, b + 3);
flag = 1;
for(int i = 0; i < 3; ++i)///若起初就相等
{
if(a[i] != b[i])
flag = 0;
}
if(flag)
return 1;
c[0][0] = b[1] + b[2] - 1, c[0][1] = b[1], c[0][2] = b[2];///b的3种下一状态
c[1][0] = b[0] + b[2] - 1, c[1][1] = b[0], c[1][2] = b[2];
c[2][0] = b[1] + b[0] - 1, c[2][1] = b[1], c[2][2] = b[0];
sort(*c, *(c + 1)), sort(*(c + 1), *(c + 2)), sort(*(c + 2), *(c + 3));
flag = 1;
for(int i = 0; i < 3; ++i)///操作之后,没有增加的项
{
for(int j = 0; j < 3; ++j)
{
if(c[i][j] > b[j])
flag = 0;
}
}
if(flag)
return 0;
int cnt = 0;
while(1)
{
cnt++;
sort(a, a + 3);
if(check())
return 1;
else if(a[0] < b[0])
return 0;
else
a[2] = a[1] - a[0] + 1;
}
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
for(int i = 0; i < 3; ++i)
scanf("%d", &a[i]);
for(int i = 0; i < 3; ++i)
scanf("%d", &b[i]);
bool flag = fun();
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}