2021 9.14 p.m. summary and Sudoku problem exploration (T3)

T1: problem A: combined output

Title Description

Permutation and combination are common mathematical methods, in which combination is to extract r elements from n elements (regardless of order and R < = n). We can simply understand n elements as natural numbers 1, 2,..., N, and take any R number from them.
Now you are required to output all combinations recursively.
For example, n = 5, r = 3, all combinations are:
l 2 3 l 2 4 1 2 5 l 3 4 l 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5

input

There are two natural numbers N and R in a row (1 < n < 21, 1 < = R < = n).

output

For all combinations, each combination occupies one line, and the elements are arranged in the order from small to large. Each element occupies the position of three characters, and all combinations are also in the order of dictionary.

sample input

5 3

sample output

  1  2  3

  1  2  4

  1  2  5

  1  3  4

  1  3  5

  1  4  5

  2  3  4

  2  3  5

  2  4  5

  3  4  5

Problem solution

This question examines the problem of permutation number. You only need to use a pd array to enumerate the number selected for each layer (each bit), and then use a VIS array to record whether it has been selected. If not, select the next one. Note that fast read and write may be used to optimize the time.

Reference code

#include<cstdio>
using namespace std;
int n,r,x[100],vis[100];
void dfs(int k)
{
	if(k==r+1)
	{
		for(int i=1;i<=r;i++)
		printf("%3d",x[i]);
		printf("\n");
		return ;
	}
	for(int i=x[k-1]+1;i<=n;i++)
	{
		if(!vis[i])
		{
			vis[i]=1;
			x[k]=i;
			dfs(k+1);
			vis[i]=0;
		}
	}
}
int main()
{
	scanf("%d%d",&n,&r);
	dfs(1);
	return 0;
}

T2: question B: ticket question

Title Description

    There are many people lining up at the door. Everyone will be given a valid password as a ticket. A valid password consists of L(3 ≤ L ≤ 15) lowercase English letters, at least one vowel (a, e, i, o or u) and two consonants (excluding vowels as syllables), and appears in alphabetical order (for example, abc is valid, but bac is not).
    Now, given a lowercase letter with the expected length of L and C(1 ≤ C ≤ 26), write a program to output all valid passwords with the length of L and can be composed of the given top C letters. The passwords must be printed in alphabetical order, one line at a time.

input

    Line 1 is two positive integers separated by a space, l and C,3 ≤ L ≤ 15, 1 ≤ C ≤ 26.
    The second line is C lowercase letters separated by a space. The password is constructed from the letters in this letter set.

output

    Several lines, each line outputs a password with a length of L characters (no spaces). The output lines must be arranged in alphabetical order. The program only needs to output the first 25000 valid passwords, even if there are still valid passwords after them.

sample input

4 6

a t c i s w

sample output

acis

acit

aciw

acst

acsw

actw

aist

aisw

aitw

astw

cist

cisw

citw

istw

Problem solution

Compared with the previous question, this question has more requirements: at least one vowel and two consonants. Therefore, we can prune in the search process. First, we can maintain a prefix and (inverted) to represent the number of subsequent vowels. During the search process, if the current enumeration reaches k, there are no vowels in front and no vowels behind (prefix and) , then you can return directly. Similarly, the processing of consonants is similar to this, except that the number is less than 2. At the same time, if the next letters are used and can not reach the specified length, you can also return. With triple pruning, you can greatly optimize the time efficiency.

Reference code

#include<cstdio>
#include<algorithm>
using namespace std;
int l,c,x[100],seg[500],p[100],vis[100],tot=0;
char s[100];int pd1[500],pd2[500],sis=0,ht[500];
bool pd(int k) { return k=='a'||k=='e'||k=='i'||k=='o'||k=='u'; }
void dfs(int k)
{
	if(tot>25000) return;
	pd1[k]=pd1[k-1];pd2[k]=pd2[k-1];
	if(k==l+1)
	{
		if(pd1[k]==0||pd2[k]<2) return;
		tot++;
		if(tot>25000) return;
		for(int i=1;i<=l;i++)
		putchar(p[i]);
		printf("\n");
		return;
	}
	for(int i=seg[p[k-1]]+1;i<=c;i++)
	{
		if(tot>25000) return;
		if(vis[i]) continue;
		if(i==sis&&pd1[k]==0) break;
		if(pd2[k]+ht[i]<2) break;
		if(c-i+1+k<l) break;
		vis[i]=1;p[k]=x[i];
		if(pd(x[i])) 
		{
			pd1[k]++;
			dfs(k+1);
			pd1[k]--;
		}
		else
		{
			pd2[k]++;
			dfs(k+1);
			pd2[k]--;
		}
		vis[i]=0;
	}
}
int main()
{
	scanf("%d%d",&l,&c);
	for(int i=1;i<=c;i++)
	{
		scanf("%s",s);
		x[i]=s[0];
	 } 
	sort(x+1,x+c+1);
	for(int i=c;i>=1;i--) 
	{
		seg[x[i]]=i;ht[i]=ht[i+1];
		if(pd(x[i])&&sis==0)
		sis=i+1;
		if(!pd(x[i]))
		ht[i]++;
	}
	dfs(1);
	return 0;
}

T3: problem C: subset and problem

Title Description

An example of the subset sum problem is [S,c]. Where s = {x1, x2,..., xn} is a set of positive integers and c is a positive integer. The subset sum problem determines whether there is a subset S1 of s so that the sum of subset S1 is equal to c.
For a given set of positive integers s = {x1, x2,..., xn} and positive integer c, program to calculate a subset S1 of s so that the sum of subset S1 is equal to c.

input

The first line has two positive integers n and c, n represents the number of S, and c is the target value of subset sum.

In the next 1 line, there are n positive integers representing the elements in the set S.

n<=8000 c<=10^7

output

Subset, and the elements are separated by spaces. When the problem has No solution, output "No solution!".

sample input

5 10

2 2 6 5 4

sample output

2 2 6

Problem solution

This problem ignores the data range. Now we only consider how to complete this problem. Similarly, use a pd array to maintain sum. If sum=c, return all. Of course, use the x array to record the selected elements. This is not enough. It needs a little pruning. If the sum at the moment is greater than c, return; if the sum of the following numbers plus sum is less than c, there is no need to continue searching, Return directly. In this way, you can find a set of answers and exit, or output no solution to the problem.

Reference code

#include<cstdio>
#define LL long long
using namespace std;
int n,c,a[10000],sum=0,sum1[10000];
int pd=0,x[10000];
void dfs(int k)
{
	if(sum+sum1[n]-sum1[x[k-1]]<c) return;
	if(pd==1) return;
	if(sum==c)
	{
		for(int i=1;i<k;i++) printf("%d ",a[x[i]]);
		pd=1;return;
	}
	for(int i=x[k-1]+1;i<=n;i++)
	{
		x[k]=i;
		if(sum+a[i]>c) continue;
		sum+=a[i];
		dfs(k+1);
		sum-=a[i];
	}
}
int main()
{
	scanf("%d%d",&n,&c);
	for(LL i=1;i<=n;i++) 
	{
		scanf("%d",&a[i]);
		sum1[i]=sum1[i-1]+a[i];
	}
	 dfs(1);
	if(pd==0) printf("No Solution!");
	return 0;
}

T5: question E: Sudoku

Title Description

Sudoku is a traditional puzzle game. You need to put a 9 × Sudoku of 9 is supplemented completely, so that each row, column and 3 in the figure × The numbers 1 ~ 9 in the Jiugong grid of 3 happen to appear once.

Please write a program to fill in Sudoku.

 

input

The input contains multiple sets of test cases.

Each test case occupies one line and contains 81 characters, representing 81 grid data of Sudoku (the order is from top to bottom, and the peers are from left to right).

Each character is a number (1-9) or a "." (indicating that it has not been filled).

You can assume that each puzzle in the input has only one solution.

A single line containing the word "end" at the end of the file indicates the end of input.

output

For each test case, a row of data is output to represent the Sudoku after filling.

sample input

.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.

......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.

sample output

527389416819426735436751829375692184194538267268174593643217958951843672782965341

416837529982465371735129468571298643293746185864351297647913852359682714128574936

Problem solution

         I also have some experience with this problem. My code doesn't lose any answers to a single nine house grid, but it just needs to run for 2s!! all my code can't pass the Sudoku problem (tears streaming down my face, konjac sadness ~) Now let's talk about this problem. First save the map with an e_map, then compress each row, column and 3 * 3 square into binary and save it. Then record the cells that have not been filled in each row (so that you don't have to look for the filled numbers repeatedly), and then search.

         The search is very simple. Just find the intersection (horizontal, vertical and square) and enumerate the numbers. Note that it is! No! Fill! So we can directly take the previous binary compression result or (^) 511 (binary 111111111), which is equivalent to taking all the negative (practical significance) After you have processed the number of this digit, consider which position to enumerate next time. At this time, I will directly use one!!! Big optimization!!! Is to enumerate the positions that can be obtained in each row backwards each time, and then... Take it directly, and add back the total number that can be filled in in the current row - 1 after backtracking. This step is very exquisite and can be dynamically pruned , and because the total array of each line of mine remains unchanged and only the tail pointer changes, the answer is also correct. See the search function in the code for this part.

          In order to further optimize, I also use bubble sorting (I think we should use fast sorting, which may be faster, but... I can't write that kind) to sort the available positions of each line. The keyword is the number that can be filled in at this position. The smaller the possibility, the less the chance of backtracking, and the faster the answer can be found. Another obvious optimization is to return directly after finding the only set of solutions, and return all running functions. Therefore, I defined ed. when ed=1, it means that the answer has been found. At this time, I made ed judgment in a large number of areas (actually 2 places) to speed up the return speed. For finding numbers, the knowledge of lowbit is also used here to optimize the selection. Those who are interested can refer to it by themselves. They can run without lowbit, just for, but they will lose more time efficiency.

         One more thing, use tot to save how many spaces are not selected at the moment. When tot=0, it means that the answer has appeared. At this moment, update ed and output the answer. It is important to pay special attention to the initialization of each function. As for those output functions, they are only for checking some things, which can be understood by themselves. How to handle 3 * 3 blocks? If you look at the code (...... ten thousand words are omitted here), you can find that the update of my array explains this. (x+2) / 3 can accurately represent the upper, middle and lower area. Similarly, it can also determine which vertical line it is in for y.

         At the end of the code, I can calculate the running time of a simple dfs. This is how I judge the time. Note that the last output millisecond is a floating point number. Use the ctime header file. Finally, various methods are used to speed up, but the effect is not obvious, which is omitted here. Last note!!! This code can quickly find an answer, but it can't pass!!!  

        By the way, this code finally has a lot of data I find myself. The answer can be photographed with the following code.

Reference code

#include<cstdio>
#include<ctime>
#include<iostream>
using namespace std;
char s[2000];int e_map[10][10],tot_x[10],max0=-1,tot=0;
int tick_x[20],tick_y[20],tick_k[5][5],st_x,st_y;
int max1(int p,int q) { return p>q?p:q; }
int ed=0,lg[1025],went[10][10],goes[10];
void outputing()
{
	for(int i=1;i<=9;i++)
		for(int j=1;j<=9;j++)
			printf("%d",e_map[i][j]);
	printf("\n");
}
void output2()
{
	for(int i=1;i<=9;i++)
	{
		for(int j=1;j<=9;j++)
	    printf("%d",e_map[i][j]);
	printf("\n");	
	}
	  printf("\n");
}
void output3(int k)
{
	for(int i=1;i<=9;i++)
	{
		printf("%d",k%2);
		k/=2;
	}
	printf("\n");
}
int search()
{
	for(int i=1;i<=9;i++)
	{
		for(int k=goes[i];k>=1;k--)
		{
			int j=went[i][k];
			st_x=i;st_y=j;
			goes[i]--;
			return i;
            //Just find a direct location
            //I'll add goes back later
		}
		
	}
}
void dfs(int x,int y)
{
	if(ed==1) return;
	if(tot==0)
	{
		outputing();
		ed=1;
		return;
	}
	int ttt=tick_x[x]^511;
    //Reverse
	while(ttt)
	{
		if(ed==1) return;
		int pk=ttt&-ttt;ttt-=pk;//lowbit access
		if((pk&tick_y[y])) continue;
		if((pk&tick_k[(x+2)/3][(y+2)/3])) continue;
        //Rows, columns and blocks do not conflict
		tick_x[x]|=pk;
		tick_y[y]|=pk;
		tick_k[(x+2)/3][(y+2)/3]|=pk;
        //Briefly update the data of the map (row column block)
		e_map[x][y]=lg[pk];
		tot--;
		int rst=search();
		dfs(st_x,st_y);
        //The key step is pruning
		goes[rst]++;
		tot++;
		tick_x[x]^=pk;
		tick_y[y]^=pk;
		tick_k[(x+2)/3][(y+2)/3]^=pk;
        //Backtracking needs to be restored
		e_map[x][y]=0;
	}
}
int main()
{
	lg[1]=1;lg[2]=2;lg[4]=3;
	lg[8]=4;lg[16]=5;lg[32]=6;
	lg[64]=7;lg[128]=8;lg[256]=9;
    //Prepare for lowbit calculation
	while(1)
	{
		tot=ed=max0=0;
		scanf("%s",s);
		if(s[0]=='e') break;
		for(int i=1;i<=3;i++)
		  for(int j=1;j<=3;j++)
		    	tick_k[i][j]=0;
        //Array initialization
		for(int i=1;i<=9;i++)
		{
			goes[i]=0;//Pointer at the end of each line
		   	tick_x[i]=0;
		   	tick_y[i]=0;
		   	for(int j=1;j<=9;j++)
		   	 went[i][j]=0;
		}
		for(int i=1;i<=9;i++)
		  for(int j=1;j<=9;j++)
		    {
		    	if(s[(i-1)*9+j-1]=='.')
		    	{
		    		went[i][++goes[i]]=j;//Record the legal position of each line
		    		e_map[i][j]=0;
		    		tot++;
				}
		    	else 
				{
                    //Binary compression
					e_map[i][j]=s[(i-1)*9+j-1]-'0';
					tick_x[i]|=(1<<(e_map[i][j]-1));
					tick_y[j]|=(1<<(e_map[i][j]-1));
					tick_k[(i+2)/3][(j+2)/3]|=(1<<(e_map[i][j]-1));
				}
			}
            //Bubble sorting
			for(int i=1;i<=9;i++)
			  for(int j=1;j<=9;j++)
			    for(int k=1;k<=9;k++)
			      if(went[i][j]>went[i][k])
			        {
			        	int c=went[i][k];
			        	went[i][k]=went[i][j];
						went[i][j]=c;
					}
			search();//Find the initial position
//			clock_t t;
//		t=clock();
		dfs(st_x,st_y);
//		t=clock()-t;
//		Cout < < time is: < ((float) t) / clocks_per_sec * 1000) < < MS \ n;	  
        //Record dfs time
	}
	return 0;
}

.................................................................................
.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
1.3...5.9..21.94.....7.4...3..5.2..6.6.....5.7..8.3..4...4.1.....92.58..8.4...1.7
8..........36......7..9.2...5...7.......457.....1...3...1....68..85...1..9....4..
..53.....8......2..7..1.5..4....53...1..7...6..32...8..6.5....9..4....3......97..
98.7..6..7......8...6.5....4....3.....89...7.....2.3...1....2....75...6......1.54
.3...7..46.2.41....5..3.967.4...3..6.87...35.9..7...2.718.2..4....16.8.94..5...3.
..5..43.1..........28..6.4....4.5...7......6.6......3...3...17....1.9.....9..2..8
.6.....75....4..9.8.3........8.9.....72..6...6..4.5...12.6......3..7.2....7..431.
...8......3..92..1.9..3....7...498....57..9..2....6.....352.1...5....4.2..6..4...
43.28...............84...1.9.3..2.4..7..3..2..5.9..8.1.2...65...............41.76
57.12...............67...8.3.4..9.7..2..7..5..1.3..9.2.8...21...............54.63
...6....7...849...28......5..7315....4..7......2......91..8..6.7......9...34..5..
75..9..469.1...3.2.........2..6.1..7.8.....2.1..3.8..5.........3.9...2.484..3..79
end

Tags: C

Posted on Sat, 18 Sep 2021 07:17:07 -0400 by RogerInHawaii