有n个水桶,组成一个环,相邻两个有水管连接,
水管中间有阀门,都关上。
初始条件是:水桶有水,深度不一,保存在数组a[n]里面。
问:设计算法,针对具体的a[n],使得打开阀门最少情况下,水桶深度相同。
时间复杂度<O(n^2),最佳是o(N).
我写的这个算法,复杂度为o(n^2),不知道能不能优化到O(n).
算法如下:
#include<iostream>
#include<list>
using namespace std;
class bucket{
public:
double water;
bool valid;
bool left;
bool right;
double orgWater;
bucket(double w):water(w){
valid=true;
left=false;
right=false;
orgWater=w;
}
};
double abs(double d){
return d>=0?d:-d;
}
list<bucket>::iterator getMaxIndex(list<bucket>& v){
double max=0;
list<bucket>::iterator index=v.end();
for(list<bucket>::iterator it=v.begin();it!=v.end();it++){
if((*it).valid&&abs((*it).water)>max){
max=abs((*it).water);
index=it;
}
}
return index;
}
void getlastIter(list<bucket>& v,list<bucket>::iterator& it){
it=v.begin();
for(int i=1;i<v.size();i++){
it++;
}
}
void moveToRight(const list<bucket>& v,list<bucket>::const_iterator& it){
it++;
if(it==v.end()){
it=v.begin();
}
if((*it).valid==true){
return;
}
else{
moveToRight(v,it);
}
}
void moveToLeft(list<bucket>& v,list<bucket>::iterator& it){
if(it==v.begin()){
getlastIter(v,it);
}else{
it--;
}
if((*it).valid==true){
return;
}
else{
moveToLeft(v,it);
}
}
bool getRight(const list<bucket> &v,const list<bucket>::iterator start,double& sum,list<bucket>::iterator it){
if(it==start)//已经转了一圈
return false;
if((*it).valid==false){
moveToRight(v,it);
return getRight(v,start,sum,it);
}else{
sum+=(*it).water;
return true;
}
}
bool getLeft(list<bucket> &v,list<bucket>::iterator start,double& sum,list<bucket>::iterator it){
if(it==start)//已经转了一圈
return false;
if((*it).valid==false){
moveToLeft(v,it);
return getLeft(v,start,sum,it);
}else{
sum+=(*it).water;
return true;
}
}
void print(const list<bucket>& l){
for(list<bucket>::const_iterator it=l.begin();it!=l.end();it++){
if((*it).right){
cout<<(*it).orgWater<<"右边打开"<<endl;
}
if((*it).left){
cout<<(*it).orgWater<<"左边打开"<<endl;
}
}
}
void init(list<bucket>& v){
double max=0;
for(list<bucket>::iterator it=v.begin();it!=v.end();it++){
max+=(*it).orgWater;
}
for(list<bucket>::iterator it=v.begin();it!=v.end();it++){
(*it).water-=max/v.size();
}
}
void algorithm(list<bucket>& v){
init(v);
list<bucket>::iterator index=getMaxIndex(v);
double max=(*index).water;
while(max!=0){
double leftSum=max;
double rightSum=max;
list<bucket>::iterator left=index;
list<bucket>::iterator right=index;
moveToLeft(v,left);
moveToRight(v,right);
while(getLeft(v,index,leftSum,left)){
getRight(v,index,rightSum,right);
moveToLeft(v,left);
moveToRight(v,right);
if(leftSum!=rightSum){
break;
}
}
if(abs(leftSum)<=abs(rightSum)){
list<bucket>::iterator temp=index;
moveToLeft(v,temp);
(*index).left=true;
(*temp).right=true;
(*temp).valid=false;
(*index).water+=(*temp).water;
}else{
list<bucket>::iterator temp=index;
moveToRight(v,temp);
(*index).right=true;
(*temp).left=true;
(*temp).valid=false;
(*index).water+=(*temp).water;
}
index=getMaxIndex(v);
if(index==v.end())
break;
max=(*index).water;
}
}
int main(){
list<bucket> v;
v.push_back(1);
v.push_back(4);
v.push_back(7);
v.push_back(1);
v.push_back(6);
v.push_back(0);
v.push_back(2);
algorithm(v);
print(v);
}
小人本潜水在思源的贴边 ID又多 又有钱 快活乐无边 谁知道站总监 他蛮横不留情面 他勾结站长目无天 占我ID夺我钱 我马甲跟他来翻脸 反被他来把经验减 我同学骂他欺新人 反被他捉进了小黑屋里面 874了一百遍啊一百遍 啊 最后他咬舌自尽 遗恨人间 他还将我和马甲赶出了思源 流落在人间 我为求回思源 无奈行乞在贴前 谁知道站总监他实在太阴险 知道此情形竟派人来暗算将我发文狂删到0篇 小人ID强 残命独留全 可怜马甲他 竟遭删 为求养ID 惟有傍人卖身自作践 一面苦赚钱 一面写诗篇 发誓把名气显 手刃总监意志坚啊 从此总监ID念心间 我永铭记此仇不供戴天 |