poj 1702
问题描述:
有一个天平和20个砝码,砝码的重量分别为1, 3, 9, 27,...,3^19,要求合理地把其中某些砝码放到天平的两边,测量出给定物体的重量w(1<w<(3^20-1)/2),待测物体放置在天平的左侧。
分析
左侧砝码总重+物体重量=右侧砝码总重
物体重量=右侧砝码总重-左侧砝码总重
所以,问题可以转化为:给出正整数w,对3^i(0<=i<=19)加上权值s (s=-1,0或者1),使得所有项的总和为w。s=-1对应于砝码放在天平左侧,s=1对应于砝码放在天平右侧,s=0对应于不使用该砝码。列举前10项的情形如下:

通过观察,这个表格和基数为3的“进位制”问题很像(如果对最基础的进位制问题的原理和方法不清楚,建议先了解一下)。我们不妨定义映射f : {0,1,2}-->{0,1,-1},即可将n%3的值相应转换为这里所要求的权值。这里还有一个问题,除第一项以外,之后每一项的“第一个周期”都是不完全的,所以对迭代过程中的n=n/3要作一个修正,考察图中的5,6,7,这三个数的后几项和2相同(红框所示),所以迭代过程应该将5,6,7转换到2,同理2,3,4-->1,8,9,10-->3等等,n=n/3最后修正为n=(n+1)/3。
核心代码
index = 0;
int table[3] = {0,1,-1};
while (n) {
num[index] = table[n%3];
n = (n+1)/3;
index++;
}
// 1702.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
using namespace std;
int main()
{
int N;
cin>>N;
int num[20];
int table[3]={0,1,-1};
long long pow3[64];
pow3[0]=1;
for(int i=1;i<64;i++)
pow3[i]=pow3[i-1]*3;
while(N--)
{
memset(num,0,20*sizeof(num[0]));
int nums;
cin>>nums;
int index=0;
while(nums)
{
num[index]=table[nums%3];
nums=(nums+1)/3;
index++;
}
bool flag=false;
int count=1;
for(int i=0;i<index;i++)
{
if(num[i]==-1)
{
flag=true;
if(count==1)
cout<<pow3[i];
else
cout<<","<<pow3[i];
count++;
}
}
if(!flag)
cout<<"empty"<<" ";
else
cout<<" ";
count=1;
for(int i=0;i<index;i++)
{
if(num[i]==1)
{
if(count==1)
cout<<pow3[i];
else
cout<<","<<pow3[i];
count++;
}
}
cout<<endl;
}
system("pause");
return 0;
}

浙公网安备 33010602011771号