正文

我的第15次编程比赛第2题程序2006-02-13 10:02:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/goal00001111/10070.html

分享到:

/*有十个开关等间距排成一线,每个开关对应其上方的一盏灯(十盏灯也排成一线)。
每按动一下开关,可以使对应的灯改变状态(原来亮着的将熄灭,原来熄灭的将被点亮)。
但是,由于开关之间的距离很小,每次按动开关时,相邻的一个开关也将被按动。
例如:按动第5个开关,则实际上第4、5、6个开关都被按动。而按动靠边的第1个开关时,
第1、2个开关都被按动。并且,无法只按动最靠边的一个开关。
现在给出十盏灯的初始的状态和目标状态,要求计算:从初始状态改变到目标状态所需要的最少操作次数。
函数接口:
int MinChange(const int Start[],const int End[]);
其中:Start表示了初始状态,End表示了目标状态。表示状态的数组(Start和End)中,
若某元素为0表示对应的灯亮着,否则表示对应的灯没有亮。调用函数时保证Start和End数组长度均为10,
并保证有解。
*操作方法:设当前灯编号为i,其下一盏灯编号为i+1
若i灯的初始状态与末状态相同,且i+1灯的初始状态与末状态相同:i = i + 1,不按开关;
若i灯的初始状态与末状态相同,但i+1灯的初始状态与末状态不同:i = i + 2,按下开关;
若i灯的初始状态与末状态不同,不论i+1灯的初始状态与末状态是否相同:i = i + 1,按下开关。
若出现无解的情况,则操作次数取32768;
从左边和右边各顺序操作一次,取操作数较小的返回
*注:因为按照如上的操作方法,最边上的两个开关是不用亲自去按的;而这样会漏掉一些解。
所以把初始状态扩展到4种情况:
1。与给定的初始状态一模一样
2。在原状态下,先按下最左边的开关
3。在原状态下,先按下最右边的开关
4。在原状态下,先按下最左边和最右边的开关
*/
/*2006-2-12 梁见斌*/
#include <iostream>
#include <cmath>

using namespace std;

int MinChange(const int Start[],const int End[]);//把初始状态扩展到四种情况
void Change(int array[], int lable, int max);//按下开关,改变对应的灯及其相邻的灯的状态
int DMinChange(const int start[], const int end[]);//按照给定操作方法操作

int main()
{
 int a[10]={1,1,1,1,1};
    int b[10]={1,0,0,0,0};
 int n = 9;

 n = MinChange(a, b);
 cout << "n=" << n << "\n";;
 
 getchar();
 return 0;
}

int MinChange(const int start[], const int end[])
{
 const int MAXLEN = 5;//存储灯的数量
 int c_start[MAXLEN]; //存储灯的初始状态
 int count;  //记录每一种初始状态下的最少操作数
 int minCount;  //记录总的最少操作数

 //从左边开始操作 
 for (int j=0; j<MAXLEN; j++) //复制数组
  c_start[j] = start[j];
 
 cout << "先不按任何开关,直接按照操作方法进行 \n";
 minCount = DMinChange(c_start, end); //先不按任何开关,直接按照操作方法进行
 
 cout << "先按下最左边的开关\n";
 Change(c_start, 0, MAXLEN - 1);//先按下最左边的开关
 count = DMinChange(c_start, end) + 1; //加上按最边上开关的操作
 minCount = (minCount < count) ? minCount : count;
 
 cout << "先按下最左边和最右边的开关\n";
 Change(c_start, MAXLEN-1, MAXLEN - 1);//先按下最左边和最右边的开关
 count = DMinChange(c_start, end) + 2; //加上按最边上开关的操作
 minCount = (minCount < count) ? minCount : count;
 
 cout << "先按下最右边的开关\n";
 Change(c_start, 0, MAXLEN - 1);//先按下最右边的开关
 count = DMinChange(c_start, end) + 1; //加上按最边上开关的操作
 minCount = (minCount < count) ? minCount : count;

 return minCount;
}
/*函数介绍:根据给定的初状态和末状态,按照操作方法顺序操作,返回所需的最少操作数 
*/
int DMinChange(const int start[], const int end[])
{
 const int MAXLEN = 5;//存储灯的数量
 int c_start[MAXLEN]; //存储灯的初始状态
 int countLeft = 0;//累计从左边开始操作的所需的操作次数
 int countRight = 0;//累计从右边开始操作的所需的操作次数
 int i;
 
 //从左边开始操作 
 for (int j=0; j<MAXLEN; j++) //复制数组
  c_start[j] = start[j];
 
 i = 0;
 while (i < MAXLEN - 1)
 {
  if (c_start[i] == end[i])//若当前灯的初始状态与末状态相同
  {
   if (c_start[i+1] == end[i+1])//若相邻的下一盏灯的初始状态与末状态相同
    i++;
   else
   {
    if (i <= MAXLEN - 3)
    {
     i += 2;
     Change(c_start, i, MAXLEN - 1);//按下开关,改变对应的灯及其相邻的灯的状态
     cout << i;     //显示操作的步骤
     countLeft ++;
    }
    else
    {
     countLeft = 32768;//出现错误的操作或无解 
     break;
    } 
   }                  
  }
  else  //若当前灯的初始状态与末状态不相同
  {
   i++;
   Change(c_start, i, MAXLEN - 1);//按下开关,改变对应的灯及其相邻的灯的状态
   cout << i;       //显示操作的步骤
   countLeft ++; 
  }
 }
 cout << "\n";
 //从右边开始操作
 for (int j=0; j<MAXLEN; j++) //复制数组
  c_start[j] = start[j];
  
 i = MAXLEN - 1; 
 while (i > 0)
 {
  if (c_start[i] == end[i])
  {
   if (c_start[i-1] == end[i-1])
    i--;
   else
   {
    if (i >= 2)
    {
     i -= 2;
     Change(c_start, i, MAXLEN - 1);//按下开关,改变对应的灯及其相邻的灯的状态
     cout << i;   //显示操作的步骤
     countRight++;
    }
    else
    {
     countRight = 32768;//出现错误的操作或无解 
     break;
    } 
   }
  }
  else
  {
   i--;
   Change(c_start, i, MAXLEN - 1);//按下开关,改变对应的灯及其相邻的灯的状态
   cout << i;      //显示操作的步骤
   countRight++; 
  }
 }
 cout << "\n";
 cout << "a=" << countLeft << "\n";   cout  << "b=" <<  countRight << "\n";
 
 return (countLeft < countRight) ? countLeft : countRight;  
}

/*函数介绍:输入一个整型数组和某元素下标,以及数组长度,改变该元素极其相邻元素的状态(0或非0) 
*/
void Change(int array[], int lable, int max)
{
 if (lable > 0)
  array[lable-1] = (array[lable-1] ? 0 : 1);
  
 array[lable] = (array[lable] ? 0 : 1);
 
 if (lable < max)
  array[lable+1] = (array[lable+1] ? 0 : 1);
}

阅读(2466) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册