Algorithm basic enumeration

Posted by bizshop on Sat, 15 Jan 2022 23:50:47 +0100

t1 fake coin poj1013

Idea:

First of all, you should know that the subject already knows the weighing results, and each input is three groups of data, so define three character arrays to store three groups of data of the left balance, three groups of data of the right balance and three groups of data of the weighing results, and then define an array to judge whether it is counterfeit money. Note that you do not know the weight of counterfeit money, so you need to judge it yourself, Then the enumeration method is used to judge whether each coin is counterfeit
 

The code is as follows:

#include<iostream>
#include <cstring>
using namespace std;
char Left[3][7];
char Right[3][7];
char result[3][7];
bool IsFake(char c, bool light);
int main() {
    int t;
    cin >> t;
    while (t--) {
        for (int i = 0; i < 3; ++i) cin >> Left[i] >> Right[i] >> result[i];
        for (char c = 'A'; c <= 'L'; c++) {
            if (IsFake(c, true)) {
                cout << c << " is the counterfeit coin and it is light.\n";
                break;
            }
            else if (IsFake(c, false)) {
                cout << c << " is the counterfeit coin and it is heavy.\n";
                break;
            }
        }
    }
    return 0;
}

bool IsFake(char c, bool light)
{
    for (int i = 0; i < 3; ++i) {
        char* pLeft, * pRight;
        if (light) {
            pLeft = Left[i];
            pRight = Right[i];
        }
        else {
            pLeft = Right[i];
            pRight = Left[i];
        }
        switch (result[i][0]) {
        case 'u':
            if (strchr(pRight, c) == NULL)
                return false;
            break;
        case 'e':
            if (strchr(pLeft, c) || strchr(pRight, c))
                return false;
            break;
        case 'd':
            if (strchr(pLeft, c) == NULL)
                return false;
            break;
        }
    }
    return true;
}

Difficulties:

Personally, the most difficult thing is to judge whether the coin is counterfeit, light or heavy. First, the function is bool type, and the incoming parameters are a character (coin) and a bool type light (weight). The first step is to define two pointers. First, assuming that the coin is light, put the coin on the left into pLeft and the coin on the right into piright, Then use the switch case function to judge the state of the balance by the initials of the result data (note that up, even and down here refer to the balance on the right, that is, up means the balance on the right rises). Therefore, if the coin is heavy, change the initial finger needle from left to right.
 

t2 lights out problem poj1222

Idea:

First of all, we need to know that to make all the lights just go out, it is determined by the lights in the first row, that is, we only need to traverse all the arrangement modes of the lights in the first row by enumerating, that is, the 6th power of 2 - 1 (0 ~ 63), until the last row also goes out as the end condition.

The code is as follows:

#include <bitset>
#include <memory>
#include <cstring>
#include <iostream>
using namespace std;
bitset<6> source[5], result[5], lights[5];
bitset<6> line; //000000~111111 0-2^6-1
void input_source()
{
	int x;
	for (int i = 0; i < 5; i++)
		for (int j = 0; j < 6; j++)
		{
			cin >> x;
			source[i][j] = x;
		}

}

void output_result()
{
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 6; j++)
			cout << result[i][j] << " ";
		cout << endl;
	}
}

int main()
{
	int t = 0;
	cin >> t;

	for (int i = 0; i < t; i++)
	{
		input_source();
		for (int n = 0; n < 64; n++)
		{
			memcpy(lights, source, sizeof(source));
			line = n;
			for (int k = 0; k < 5; k++)
			{
				result[k] = line;
				for (int j = 0; j < 6; j++)
				{
					if (line.test(j))
					{
						lights[k][j].flip();
						lights[k + 1][j].flip();
						if (j > 0)	lights[k][j - 1].flip();
						if (j < 5) lights[k][j + 1].flip();
						
					}
				}
				line = lights[k];
			}
			if (lights[4].none())
			{
				cout << "PUZZLE #" << i + 1 << endl;
				output_result();
				break;
			}
		}

	}

}

Difficulties:

The matrix formed by binary 0 and 1 is used to replace the extinguishment of the lamp. Here, the bitset library is called to define a combination of 5 lines and 6 bits, and then it is written according to the analysis of the topic

t3 special password lock openjudge 8469

Idea:
Much like the problem of turning off the light (poj p1222), just enumerate the two cases of whether the first button is pressed or not. Moreover, the first case is determined, and the latter case is also determined.

The code is as follows:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
//Just enumerate whether the first button is pressed or not. For a specified case, the latter case is also determined 
int orilock;
int lock;
int destlock;
 void setbit(int& n, int i, int v)//Set the i-th position of n to v 
{
	if (v)
		n |= (1 << i);
	else
		n &= ~(1 << i);
}

 void flipbit(int& n, int i)//Negate the i-th bit of n 
{
	n ^= (1 << i);
}

 int getbit(int n, int i)//Take the i-th bit of n 
{
	return (n >> i) & 1;
}

int main()
{
	char line[40];
	destlock = lock = orilock = 0;
	cin >> line;
	int n = strlen(line);
	for (int i = 0; i < n; ++i)
		setbit(orilock, i, line[i] - '0');
	cin >> line;
	for (int i = 0;  i < n; ++i)
		setbit(destlock, i, line[i] - '0');
	int mintimes = 1 << 30	;
	for (int p = 0; p < 2; ++p)//The first button can be pressed or not 
	{
		lock = orilock;
		int times = 0;
		int curbutton = p;
		for (int i = 0; i < n; ++i)
		{
			if (curbutton)
			{
				++times;
				if (i > 0)
					flipbit(lock, i - 1);
				flipbit(lock, i);
				if (i < n - 1)
					flipbit(lock, i + 1);
			}
			if (getbit(lock, i) != getbit(destlock, i))
				curbutton = 1;
			else
				curbutton = 0;
		}
		if (lock == destlock)
			mintimes = min(mintimes, times);
	}
	if (mintimes == 1 << 30)
		cout << "impossible" << endl;
	else
		cout << mintimes << endl;
	return 0;
}

Summary:

I also learned algorithms for the first time and didn't understand them. I wrote this to summarize my learning. If I don't understand the meaning of the code, I can substitute the data into the draft paper for calculation. I learned it by video on mooc (I read it many times). In short, algorithm learning is a long and difficult process, If you don't understand the first time, read it for the second time until you understand it. Come on!

Topics: C++ Algorithm