Number Game( ZOJ - 3180,思维 + 逆推)

一.题目链接:

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;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值