Light Bulbs

	The 2003 27 th Annual ACM International Collegiate
	Programming Contest World Finals
	sponsored by IBM
	Problem B
	

Read my solution

Hollywood's newest theater, the Atheneum of Culture and Movies, has a huge computer-operated marquee composed of thousands of light bulbs. Each row of bulbs is operated by a set of switches that are electronically controlled by a computer program. Unfortunately, the electrician installed the wrong kind of switches, and tonight is the ACM's opening night. You must write a program to make the switches perform correctly. A row of the marquee contains n light bulbs controlled by n switches. Bulbs and switches are numbered from 1 to n, left to right. Each bulb can either be ON or OFF. Each input case will contain the initial state and the desired final state for a single row of bulbs.

The original lighting plan was to have each switch control a single bulb. However the electrician's error caused each switch to control two or three consecutive bulbs, as shown in Figure 1. The leftmost switch (i = 1) toggles the states of the two leftmost bulbs (1 and 2); the rightmost switch (i = n) toggles the states of the two rightmost bulbs (n-1 and n). Each remaining switch (1 < i < n) toggles the states of the three bulbs with indices i-1, i, and i+1. (In the special case where there is a single bulb and a single switch, the switch simply toggles the state of that bulb.) Thus, if bulb 1 is ON and bulb 2 is OFF, flipping switch 1 will turn bulb 1 OFF and bulb 2 ON. The minimum cost of changing a row of bulbs from an initial configuration to a final configuration is the minimum number of switches that must be flipped to achieve the change.

You can represent the state of a row of bulbs in binary, where 0 means the bulb is OFF and 1 means the bulb is ON. For instance, 01100 represents a row of five bulbs in which the second and third bulbs are both ON. You could transform this state into 10000 by flipping switches 1, 4, and 5, but it would be less costly to simply flip switch 2. You must write a program that determines the switches that must be flipped to change a row of light bulbs from its initial state to its desired final state with minimal cost. Some combinations of initial and final states may not be feasible. For compactness of representation, decimal integers are used instead of binary for the bulb configurations. Thus, 01100 and 10000 are represented by the decimal integers 12 and 16.

Input

The input file contains several test cases. Each test case consists of one line. The line contains two non-negative decimal integers, at least one of which is positive and each of which contains at most 100 digits. The first integer represents the initial state of the row of bulbs and the second integer represents the final state of the row. The binary equivalent of these integers represents the initial and final states of the bulbs, where 1 means ON and 0 means OFF.

To avoid problems with leading zeros, assume that the first bulb in either the initial or the final configuration (or both) is ON. There are no leading or trailing blanks in the input lines, no leading zeros in the two decimal integers, and the initial and final states are separated by a single blank.

The last test case is followed by a line containing two zeros.

Output

For each test case, print a line containing the case number and a decimal integer representing a minimum-cost set of switches that need to be flipped to convert the row of bulbs from initial state to final state. In the binary equivalent of this integer, the rightmost (least significant) bit represents the n th switch, 1 indicates that a switch has been flipped, and 0 indicates that the switch has not been flipped. If there is no solution, print "impossible". If there is more than one solution, print the one with the smallest decimal equivalent.

Print a blank line between cases. Use the output format shown in the example.

        Sample Input                        Output for the Sample Input
        12 16                               Case Number 1: 8
        1 1
        3 0                                 Case Number 2: 0
        30 5
        7038312 7427958190                  Case Number 3: 1
        4253404109 657546225
        0 0                                 Case Number 4: 10

                                            Case Number 5: 2805591535
					
                                            Case Number 6: impossible
	

A Solution Using Backtracking

#include <vector>
#include <string>
#include <iostream>
using namespace std;

namespace lightbulbs_acm_programming_contest_world_final_2003b {
		
		// The function decimals2binarys will generate a binary string based on the input decimal string
		// sample input      sample output
		// "16"              "10000"
		// "3"               "11"
		// "12"              "1100"
		// "1025"            "10000000001"
		// Please note that the dec_str could be as long as 100 decimal digits, so the routine should be
		// generic enough to handle very long strings.
			
		string decimals2binarys(string dec_str)
		{
			string binary_s;
			size_t next = 0;
			size_t et = dec_str.size();
			do {
				int r = 0;
				size_t st = next;
				while (st < et)
				{
					int d = 0;
					d = r * 10 + dec_str[st]-'0';
					r = d%2;
					d = d/2;
					dec_str[st++] = d+'0';
				}
				binary_s.insert(binary_s.begin(),r+'0');
				while(next<et&&dec_str[next]=='0')
					next++;
			} while(next<et);
			return binary_s;
		}
			
		
		// The function binarys2hexs will convert a binary string to a hexical string.
		// sample input             sample output
		// "1011"                   "B"
		// "10000"                  "10"
		// "11010"                  "1A"
		// "101010001111"           "A8F"
		string binarys2hexs(string bstr)
		{
			string hexs;
			size_t et = bstr.size();
			while(et>0)
			{
				size_t st;
				if (et<4)
					st = 0;
				else
					st = et-4;
				int d=0;
				for (size_t i=st; i<et; i++)
					d = d*2+bstr[i]-'0';
				char h;
				if (d<10)
					h = '0'+d;
				else
					h = 'A'+d-10;
				hexs.insert(hexs.begin(),h);
				et = st;
			}
			return hexs;
		}

		// The hexs2decimals function will convert hexical string to decimal string with equal value
		// Sample input (input hex string)                              Sample output (return string)
		// "FF"                                                         "255"
		// "FFEE"                                                       "65518"
		// "FFFF"                                                       "65535"
		// "10"                                                         "16"
		string hexs2decimals(string hexs)
		{
			string decimal_s;
			size_t next = 0;
			size_t et = hexs.size();

			do {
				int r = 0;
				size_t st = next;
				while (st < et)
				{
					int d = 0;
					d = r * 16 + (hexs[st]>='0'&&hexs[st]<='9'?(hexs[st]-'0'):(10+hexs[st]-'A'));
					r = d%10;
					d = d/10;
					hexs[st++] = (d>=0&&d<=9)?(d+'0'):('A'+d-10);
				}
				char c=r+'0';
				decimal_s.insert(decimal_s.begin(),c);
				while(next<et&&hexs[next]=='0')
					next++;
			} while(next<et);
			return decimal_s;
		}

		// The function binarys2decimals will generate a decimal string based on the input binary string
		// sample input      sample output
		// "10000"           "16"
		// "11"              "3"              
		// "1100"            "12"
		// "10000000001"     "1025"
		string binarys2decimals(string binary_str)
		{
			return hexs2decimals(binarys2hexs(binary_str));
		}

		// xor_char implements XOR on two chars represent 0 and 1
		// sample input          sample output
		// 0 0                   0
		// 0 1                   1
		// 1 0                   1
		// 1 1                   0
		inline char xor_char(char c1, char c2)
		{
			return (c1==c2)?'0':'1';
		}

		// xor_bstr implements XOR on two binary strings
		// sample input          sample output
		// 1001       1          1000
		// 1010      11          1001
		// 1100    1011          0111
		// 1111     111          1000
		string xor_bstr(string &op1, string &op2)
		{
			string s;

			string::reverse_iterator it1=op1.rbegin(), it2=op2.rbegin();
			for(; it1!=op1.rend()&&it2!=op2.rend(); it1++, it2++)
				s.insert(s.begin(), xor_char(*it1,*it2));
			if(it1!=op1.rend())
			{
				for(;it1!=op1.rend();it1++)
					s.insert(s.begin(), *it1);
			}
			else if(it2!=op2.rend())
			{
				for(;it2!=op2.rend();it2++)
					s.insert(s.begin(), *it2);
			}
			return s;
		}

		// flipchar implements flip operation on 0 and 1 represented by char
		// sample input     sample output
		//            1     0
		//            0     1
		inline char flipchar(char c)
		{
			return (c=='0')?'1':'0';
		}

		// calculate the cost of a solution i.e. number of '1' in a binary string
		// sample input                sample output
		// 1001000                     2
		// 0010000                     1
		// 1110000                     3
		int costof(string switches)
		{
			int cost = 0;

			for (size_t t = 0; t<switches.size(); t++)
				if (switches[t]=='1')
					++cost;
			return cost;
		}

		// search_solution function will start constructing with a partial solution described 
		// by:
		// diff_stat -- difference state upon which the solution will apply
		// prev -- with any pre[i] is the state of i after applying solution[i-1] 
		//         and solution[i] upon diff_stat
		// solution -- light switches
		// current_idx -- current light bulb state to consider
		// startswitch -- '0' or '1' to indicate ON or OFF switch to try 
		//
		bool search_solution(const string &diff_stat, string &prev, string &solution,
					size_t &current_idx, char startswitch)
		{
			size_t first_idx = current_idx;
			while(current_idx<solution.size())
			{
				if (current_idx==0)
				{
					if (startswitch=='0')
					{
						solution[current_idx] = '0';
						prev[current_idx] = diff_stat[current_idx];
					}
					else
					{
						solution[current_idx] = '1';
						prev[current_idx] = flipchar(diff_stat[current_idx]);
					}
				}
				else
				{
					if (prev[current_idx-1]=='0')
					{
						if (current_idx==first_idx&&startswitch=='1') //start with '1', violate last bit state
							return false;
						solution[current_idx] = '0'; //current switch off
						prev[current_idx] = (solution[current_idx-1]=='0')?diff_stat[current_idx]:
												flipchar(diff_stat[current_idx]); //flip by last switch
					}
					else // prev[current_idx-1]=='1'
					{
						solution[current_idx] = '1';
						prev[current_idx] = (solution[current_idx-1]=='1')?diff_stat[current_idx]:
												flipchar(diff_stat[current_idx]);
					}
				}
				current_idx++;
			}
			return prev[current_idx-1]=='0';
		}

		// lightbulbs function will search for solution of minimal cost based on the initial
		// state, final state, and print the result with case number.
		void lightbulbs(string init_stat, string final_stat, int caseno)
		{
			init_stat = decimals2binarys(init_stat);
			final_stat = decimals2binarys(final_stat);

			string diff_stat = xor_bstr(init_stat,final_stat);

			//our goal is to change diff_stat to 0 by applying the light switches
			string	minimalcost_solution;
			int		mincost;
			string solution(diff_stat.size(),'0');
			string prev(diff_stat.size(),'0');
			size_t current_idx = 0;
			char   startswitch = '0';
			//backtracking
			do {
				bool res = search_solution(diff_stat, prev, solution, current_idx, startswitch);
				if (res==true)
				{ 
					if (minimalcost_solution.size()==0)
					{
						minimalcost_solution = solution;
						mincost = costof(solution);
					}
					else
					{
						if (costof(solution)<mincost)
						{
							minimalcost_solution = solution;
							mincost = costof(solution);
						}
					}
				}
				//backtracking
				while(current_idx>0&&solution[current_idx-1]=='1')
						current_idx--;
				if (current_idx==0)
					{	//no more solution
						break;
					}
				--current_idx;
				startswitch = '1';
			}while(1);
			if (minimalcost_solution.size()>0)
				cout<<"Case Number "<<caseno<<": "<<binarys2decimals(minimalcost_solution)<<endl;
			else
				cout<<"Case Number "<<caseno<<": impossible"<<endl;

		}

		// lightbulbs_solver() will first read in all pairs of initial/final states. It will try to solve
		// each pair of initial/final state by calling lightbulbs function, which will find a minimal cost
		// solution that consists of a string of ON/OFF switches. By applying the solution to the light bulbs
		// with the initial state, those light bulbs will turn into the final state. 
		// If a solution does not exist for a pair of initial/final state, lightbulbs function will print "impossible"
		// with the case number.
		void lightbulbs_solver()
		{
			vector<string> init_stats;
			vector<string> final_stats;

			string init_s, final_s;
			do
			{
				cin>>init_s;
				cin>>final_s;
				if (init_s!="0"||final_s!="0")
				{
					init_stats.push_back(init_s);
					final_stats.push_back(final_s);
				}
				else
					break;
			} while(1);
			for (size_t t=0; t<init_stats.size(); t++)
			{
				if (t!=0) 
					cout<<endl; //print blank line between cases
				lightbulbs(init_stats[t], final_stats[t], (int)t+1);
			}
		}
}