UVAlive 6160 Countdown 解题报告

题目

题意:

给出6个数,可以任意做四则运算,但是每个数和每个等式的结果只能用一次,任何时候运算结果都要求是正整数。问能否能得出指定的值,如果不能,要求得到最接近的值。要求输出解,不要所有数字都用上,也不要求输出的过程个个都有用。

题解:

每次枚举剩下的数和结果里选两个枚举运算方式,将结果放进去再dfs。

做之前先把6个数排序,如果两次枚举的数和上次一样,就不用再做了。加上这个剪枝可以快很多。本来想插入新结果再排序的,不过效果反而差。


//Time:3869ms
//Memory:0KB
//Length:2370B
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 710
#define MAXM 60010
#define MOD 1000000007
#define INF 1000000007
#define FI first
#define SE second
struct _node
{
    int a,b,c;
    long long d;
    void init(int aa,int bb,int cc,long long dd)
    {
        a=aa,b=bb,c=cc,d=dd;
    }
};
const char ope[10]="+-*/";
int tar,top;
long long best,num[10];
_node sta[10];
_node ans[10];
void upd(int h,long long now)
{
    for(int i=0;i<h;++i)
        ans[i]=sta[i];
    best=now;
    top=h;
}
void print()
{
    printf("Target: %d\n",tar);
    for(int i=0;i<top;++i)
    {
        printf("%d %c %d = %lld\n",ans[i].a,ope[ans[i].b],ans[i].c,ans[i].d);
    }
    printf("Best approx: ");
    cout<<best<<"\n\n";
}
bool dfs(int h,long long arr[])
{
    for(int i=0;i<h;++i)
    {
        if(arr[i]==tar)
        {
            upd(6-h,arr[i]);
            return true;
        }
        else    if(abs(best-tar)>abs(tar-arr[i]))
            upd(6-h,arr[i]);
    }
    if(h==1)    return false;
    long long tmp[6];
    bool flag=0;
    for(int i=0;i<h&&!flag;++i)
        for(int j=0;j<h&&!flag;++j)
            if(i!=j&&(j==0||arr[j]!=arr[j-1]))
                for(int k=0;k<4&&!flag;++k)
                {
                    for(int l=0,cnt=0;l<h;++l)
                        if(l!=i&&l!=j)  tmp[cnt++]=arr[l];
                    if(k==0)
                        tmp[h-2]=arr[i]+arr[j],sta[6-h].init(arr[i],k,arr[j],tmp[h-2]),flag=dfs(h-1,tmp);
                    if(!flag&&k==1&&arr[i]>arr[j])
                        tmp[h-2]=arr[i]-arr[j],sta[6-h].init(arr[i],k,arr[j],tmp[h-2]),flag=dfs(h-1,tmp);
                    if(!flag&&k==2)
                        tmp[h-2]=arr[i]*arr[j],sta[6-h].init(arr[i],k,arr[j],tmp[h-2]),flag=dfs(h-1,tmp);
                    if(!flag&&k==3&&(arr[i]%arr[j]==0))
                        tmp[h-2]=arr[i]/arr[j],sta[6-h].init(arr[i],k,arr[j],tmp[h-2]),flag=dfs(h-1,tmp);

                }
    return flag;
}
int main()
{
    //freopen("/home/moor/Code/input","r",stdin);
    int ncase;
    scanf("%d",&ncase);
    for(int hh=1;hh<=ncase;++hh)
    {
        for(int i=0;i<6;++i)    scanf("%lld",&num[i]);
        scanf("%d",&tar);
        best=INF;
        sort(num,num+6);
        dfs(6,num);
        print();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值