Eva's Balance

题目:

Eva's Balance
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 4220 Accepted: 2025

Description

Eva has a balance with 20 poises. The weights of the poises are 1, 3, 9, 27,...,3^19. Eva asserts that she has a way to measure any object whose weight is an integer from 1 to (3^20-1)/2. Assuming that Eva has placed an object with the weight in this range on the left tray of the balance, your task is to place the proper poises on the proper trays so as to weigh the object out.

Input

The first line is an integer T (1 <= T <= 20), which shows the number of the test cases. Each of the following T lines contains an integer W (1 <= W <= (3^20-1)/2), expressing the weight of an object.

Output

For each test case print a line, showing the weights of the poises on the left tray and the right tray. Use a space to separate the left tray and the right tray. The poises on the same tray are arranged in the increasing order, and a comma separates every two of them. If there is no poise on the tray, output "empty".

Sample Input

3
9
5
20

Sample Output

empty 9
1,3 9
1,9 3,27


心得:


 首先想到的是转换成背包问题,可是放入背包的物体不能确定,就想着怎样确定用来平衡物体的数。确定数后,发现背包问题,用贪心算法,我只能知道结果,中间放物体的过程,我不会表示,就想着再换一种思路,发现多机调度问题    和这题很相似(有两台机器,作业为本身的物体和后来确定的用来平衡的物体,使时间最少,就是两台机器上作业的和相等),而且可以知道中间运作的过程,就知道那些数放入机器1,哪些放入机器2了,从而知道左盘(包括本身的物体的数)和右盘上的数,最后按要求输出。
步骤
1.下面就  找规律  ,确定用来平衡物体的数。写出了Randw()函数。(这是一个痛苦的过程,我用了好长时间,写了许多例子)。
2.将问题转换成多机调度问题。
3.按要求输出。




代码<C语言>:

#include<stdio.h>
#include<math.h>
int Randw(long c[],int w);
void Readc(long c[]);
int main()
{
    int n,w,i,j,x,y,t,f,p,q,g,k,m,sum=0,sum1,sum2;
    long c[25],a[25],L[25],R[25];
    memset(L,0,sizeof(L));//初始化数组
    memset(R,0,sizeof(R));
    scanf("%d",&n);//输入要测试的次数
    while(n--)
    {
        y=0;
        scanf("%d",&w);//输入物体的重量
        m=w;
        Readc(c);
        for(i=0; i<20; i++)
        {
            if(c[i]==m)//如果物体的重量正好等于数组c[i]
                y=1;


        }
        if(y)
        printf("empty %d\n",m);//c[i]是砝码的数组


        else
        {
            a[0]=w;//确定数组a[i],w是物体的质量
            for(i=1; w>0; i++)
            {
                k=Randw(c,w);//确定了物体所在质量区间
                //printf("这里是k的值:%d\n",k);
                a[i]=c[k];
                //printf("这里是c[%d]的值%d\n",i,c[k]);
                //sum=sum+a[i];//计算出总和
                w=fabs(w-c[k]);
                //printf("这是w:%d\n",w);
            }
            x=i;//数组a[]有i个数


            for(i=0; i<x-1; i++)//以下将a[i]从高到底排序
            {
                for(j=i+1; j<x; j++)
                {
                    if(a[j]>a[i])
                    {
                        t=a[j];
                        a[j]=a[i];
                        a[i]=t;
                    }
                }
            }


            //转换成  多机调度问题: 有两台机器,有a[]作业,时间最少的运做方式就是左右两盘的摆放方式
            f=1;
            g=1;
            L[0]=a[0];
            R[0]=a[1];
            sum1=L[0];
            sum2=R[0];//将最大的两个数,分别放入两个机器
            for(i=2; i<x; i++)
            {
                if(sum1>=sum2)//将物体从大到小放入当前运行时间较短的机器
                {
                    sum2=sum2+a[i];
                    R[f]=a[i];
                    f++;//f为R[i]的个数
                }
                else
                {
                    sum1=sum1+a[i];
                    L[g]=a[i];
                    g++;
                }
            }
            //以下输出左盘右盘上的数
            for(i=0; i<g; i++)
            {
                if(L[i]==m)//L[i]是左盘上的物品,R[i]是右盘上的物品,因为w物体放在左盘
                {
                    p=i;
                    for(i=p; i<g-1; i++) //将数组中为w的数覆盖掉,数组有g-1个数,重新确定数组L[i]
                    {
                        L[i]=L[i+1] ;
                    }
                    if(g-1==0)
                        printf("empty");
                    else
                    {
                        if(g>=2)
                        {
                            printf("%d",L[g-2]);
                        }//输出最小的数
                        if(g>=3)
                        {
                            for(i=g-3; i>=0; i--)
                            {
                                printf(",%d",L[i]);
                            }
                        }
                    }
                    printf(" ");//左右两盘之间用空格隔开
                    if(f>=1)
                    {
                        printf("%d",R[f-1]);
                    }//输出最小的数(为了使两个数之间有逗号)
                    if(f>=2)
                    {
                        for(i=f-2; i>=0; i--)
                        {
                            printf(",%d",R[i]);
                        }


                    }
                    printf("\n");
                    break;
                }
            }
            for(i=0; i<f; i++)
            {
                if(R[i]==m)//R[i]是左盘上的物品,R[i]是右盘上的物品


                {
                    q=i;
                    for(i=q; i<f-1; i++) //将数组中为w的数覆盖掉,数组有f-1个数
                    {
                        R[i]=R[i+1] ;
                    }
                    if(f-1==0)
                        printf("empty");
                    else
                    {
                        if(f>=2)
                        {
                            printf("%d",R[f-2]);
                        }//输出最小的数
                        if(f>=3)
                        {
                            for(i=f-3; i>=0; i--)
                            {
                                printf(",%d",R[i]);
                            }
                        }
                    }
                    printf(" ");
                    if(g>=1)
                    {
                        printf("%d",L[g-1]);
                    }//输出最小的数
                    if(g>=2)
                    {
                        for(i=g-2; i>=0; i--)
                        {
                            printf(",%d",L[i]);
                        }


                    }
                    printf("\n");
                    break;
                }
            }
        }
    }


    return 0;
}
void Readc(long c[])
{
    int i;
    c[0]=0;
    for(i=1; i<22; i++)
    {
        c[i]=pow(3,i-1);
        //printf("c[%d]的值为:%d\n",i,c[i]);
    }
}
int Randw(long c[],int w)//c[i]为砝码的合集
{
    int sum=0,sum1,i;
    for(i=0; i<22; i++)
    {
        sum=sum+c[i];
        sum1=sum+c[i+1];
        if(w>sum&&w<=sum1)
        {
            return i+1;
        }
    }
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值