Blue Bridge Cup - 2015 6th C/C++ Zhenti [Provincial Competition] [Group B]

content

1. Number of lottery tickets (fill in the blank)

2. Galaxy Bomb (Fill in the result)

3. Sanyang Xianrui (Fill in the blank)

4. Output in the grid (code to fill in the blanks)

5. Scores in nine groups (fill in the blanks)

6. Addition to Multiplication (Fill in the result)

7. Number of card types (fill in the blank)

8. Moving distance (programming question)

9. Rolling dice (programming questions)

10. The Tree of Life (Programming Question)

11. Summary


1. Number of lottery tickets (fill in the blank)

Some people are very superstitious about numbers, such as numbers with "4", and think that it is homophonic with "death", which is considered unlucky.
Although these claims are pure nonsense, but sometimes also cater to the needs of the public. The lottery number of a certain lottery is 5 digits (10000-99999). It is required that the number with "4" should not appear in it. The organizer asks you to calculate, if any two lottery coupons are not duplicated, the maximum number of lottery coupons can be issued.
Please submit this number (an integer) without any superfluous or descriptive text.

Idea: This question is very simple. I provide two methods here. The first method is to directly take the remainder of the number in the range. If it is equal to a digit equal to 4, skip it. If it is not equal to 4, then ++. Convert the numbers inside into strings, and use find to find whether there is 4 in each number;

method one:

#include<iostream>
using namespace std;
int cnt = 0;
bool f(int x)
{
	while (x > 0)
	{
		int m = x % 10;
		if (m == 4)
		{
			return false;
		}
		x /= 10;
	}
	return true;
}
int main()
{
	for (int i = 10000; i <= 99999; i++)
	{
		if (f(i))
		{
			cnt++;
		}
	}
	cout << cnt << endl;
	return 0;
}

Method Two:

#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int ants;
void i2s(int i, string& s)
{
	stringstream ss;
	ss << i;
	ss >> s;
}
int main()
{
	for (int i = 10000; i <= 99999; i++)
	{
		string s;
		i2s(i,s);
		if (s.find('4') == string::npos)
		{
			ants++;
		}
	}
	cout << ants << endl;
	return 0;
}

Answer: 52488 

2. Galaxy Bomb (Fill in the result)

There are many X-star man-made "bombs" floating in the vast expanse of galaxy X, which are used as road signs in the universe.
Each bomb can be set to detonate after a set number of days.
For example: if the Alpha bomb was placed on January 1, 2015, and the timing was 15 days, it would explode on January 16, 2015.
There is a beta bomb, placed on November 9, 2014, with a timing of 1000 days, please calculate the exact date it exploded.

Please fill in the date in the format of yyyy-mm-dd, that is, 4 digits for the year, 2 digits for the month, and 2 digits for the date. For example: 2015-02-19
Please write in strict accordance with the format. No other words or symbols may appear.

 Idea: Because this is a fill-in-the-blank question, we can do it with the excel that comes with the computer, and there is a calculator attached to the menu bar.

method one:

Method 2: Code Implementation

#include<iostream>
using namespace std;
class Date {
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	int GetMonthDay(int year, int month)
	{
		static int monthDayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		int day = monthDayArray[month];
		// 365天 5小时+
		if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		{
			day += 1;
		}

		return day;
	}
	Date& operator+=(int day)
	{
		_day += day;
		while (_day > GetMonthDay(_year, _month))
		{
			_day -= GetMonthDay(_year, _month);
			++_month;

			if (_month == 13)
			{
				_month = 1;
				_year++;
			}
		}

		return *this;
	}
	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2014, 11, 9);
	d1 += 1000;
	d1.print();
	return 0;
}

Answer: 2017-8-5 

3. Sanyang Xianrui (Fill in the blank)

Observe the following addition algorithm:

    Xiangruishenghui
 + Sanyang Xianrui
 ------------------- Sanyang
Shengqiang

(If there is an alignment problem, please refer to [Figure 1.jpg])

Among them, the same Chinese characters represent the same numbers, and different Chinese characters represent different numbers.

Please fill in the 4-digit number represented by "Sanyang Xianrui" (the answer is unique), and do not fill in any redundant content.

Idea: This question can be enumerated violently with 8 for loops. Anyway, it is a fill-in-the-blank question, without considering the efficiency problem. You can also use the next_permutation in the STL library for full arrangement, and then judge whether it meets the meaning of the question; the last method is Combine mathematical ideas to reduce for loops and improve algorithm efficiency

三 -> a -> a[0]

羊 -> b -> a[1]

献 -> c -> a[2]

瑞 -> d -> a[3]

祥 -> e -> a[4]

生 -> f -> a[5]

辉 -> g -> a[6]

气 -> h -> a[7]

Method 1: Violent enumeration, replace eight Chinese characters with eight different letters ah

#include<iostream>
#include<bits/stdc++.h>
int main(){
	int sum, sum1, sum2;
	for(int a=1;a<=9;a++){ //a 不能等于 0 
		for(int b=0;b<=9;b++){
			if(b!=a){
				for(int c=0;c<=9;c++){
					if(c!=a&&c!=b){
						for(int d=0;d<=9;d++){
							if(d!=a&&d!=b&&d!=c){
								for(int e=1;e<=9;e++){ //e 不能等于 0 
									if(e!=a&&e!=b&&e!=c&&e!=d){
										for(int f=0;f<=9;f++){
											if(f!=a&&f!=b&&f!=c&&f!=d&&f!=e){
												for(int g=0;g<=9;g++){
													if(g!=a&&g!=b&&g!=c&&g!=d&&g!=e&&g!=f){
														for(int h=0;h<=9;h++){
															if(h!=a&&h!=b&&h!=c&&h!=d&&h!=e&&h!=f&&h!=g){
																sum1=e*1000+d*100+f*10+g;
																sum2=a*1000+b*100+c*10+d;
																sum=a*10000+b*1000+f*100+d*10+h;
																if(sum==(sum1+sum2)){
																	printf("%d\n",sum2);
																}
															}
															
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	return 0;
}

Method 2: Use the next_permutation in the STL library to arrange all; use the array a to replace the letters

//  a[4] a[3] a[5] a[6]
//+ a[0] a[1] a[2] a[3]
//------------------------------ -
//a[0] a[1] a[5] a[3] a[7]
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{

	int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
	int sum1 = 0;
	int sum2 = 0;
	int sum = 0;
	while (next_permutation(a, a + 10))
	{
		if (a[0] != 0 && a[4] != 0)
		{
			sum1 = a[4] * 1000 + a[3] * 100 + a[5] * 10 + a[6];
			sum2 = a[0] * 1000 + a[1] * 100 + a[2] * 10 + a[3];
			sum = a[0] * 10000 + a[1] * 1000 + a[5] * 100 + a[3] * 10 + a[7];
			if ((sum1 + sum2) == sum)
			{
				break;
			}
		}
	}
	cout << sum2 << endl;
	return 0;
}

Answer: 1085 

4. Output in the grid (code to fill in the blanks)

The StringInGrid function prints the specified string in a grid of the specified size.
The string is required to be centered both horizontally and vertically.
If the string is too long, it is truncated.
If it can't be exactly centered, it can be slightly left or slightly up.
The following program implements this logic, please fill in the missing code in the underlined part.

#include <stdio.h>
#include <string.h>
void StringInGrid(int width, int height, const char* s)
{
 int i,k;
 char buf[1000];
 strcpy(buf, s);
 if(strlen(s)>width-2) buf[width-2]=0;
 
 printf("+");
 for(i=0;i<width-2;i++) printf("-");
 printf("+\n");
 
 for(k=1; k<(height-1)/2;k++){
  printf("|");
  for(i=0;i<width-2;i++) printf(" ");
  printf("|\n");
 }
 
 printf("|");
 
 printf("%*s%s%*s",_____________________________________________);  //填空
          
 printf("|\n");
 
 for(k=(height-1)/2+1; k<height-1; k++){
  printf("|");
  for(i=0;i<width-2;i++) printf(" ");
  printf("|\n");
 } 
 
 printf("+");
 for(i=0;i<width-2;i++) printf("-");
 printf("+\n"); 
}
int main()
{
 StringInGrid(20,6,"abcd1234");
 return 0;
}

 For the data in the title, it should output:
+--------+
| |
| abcd1234 |
| |
| |
+------------ ------+
Ideas: To do this kind of code fill-in-the-blank question, first, we comment out the place to be filled in, and then run it to see the effect,

That is, we need to locate the position of the character, and then look at the code segment that needs to be filled in

printf("%*s%s%*s",_____________________________________________);  

 *s This test is relatively biased, but we can check cplusplus for nothing.

 In fact, it is equivalent to a placeholder

Here we know, that is, the width width minus the length of the string minus 2 and the whole divided by 2 to get the answer.

答案:(width-2-strlen(buf))/2,"",buf,(width-2-strlen(buf))/2,"") 

5. Scores in nine groups (fill in the blanks)

1,2,3...9 These nine numbers form a fraction, and its value is exactly 1/3. How to make it?
The following program implements this function, please fill in the missing code in the underlined part.

#include <stdio.h>
void test(int x[])
{
int a = x[0]*1000 + x[1]*100 + x[2]*10 + x[3];
int b = x[4]*10000 + x[5]*1000 + x[6]*100 + x[7]*10 + x[8];

if(a*3==b) printf("%d / %d\n", a, b);
}

void f(int x[], int k)
{
int i,t;
if(k>=9){
test(x);
return;
}

for(i=k; i<9; i++){
{t=x[k]; x[k]=x[i]; x[i]=t;}
f(x,k+1);
_____________________________________________ // 填空处
}
}

int main()
{
int x[] = {1,2,3,4,5,6,7,8,9};
f(x,0);  
return 0;
}

 Ideas: In fact, everyone who has read my previous blog knows that this is a full array template, recursive backtracking, you can directly fill in the answer,

答案:t=x[k];x[k]=x[i];x[i]=t;

6. Addition to Multiplication (Fill in the result)

We all know: 1+2+3+…+49 = 1225
now requires you to turn two of the non-adjacent plus signs into multiplication signs, making the result 2015

For example:
1+2+3+…+10*11+12+…+27*28+29+…+49 = 2015
is the answer that meets the requirements.

Please look for another possible answer and submit the number to the left of the first multiplication sign (for the example, submit 10).

 Idea: This question is actually an enumeration. We need to enumerate the positions of two multiplication signs, the position of the first multiplication sign, starting from 1 and up to 46 positions, so as to ensure that they are not adjacent and have the second multiplication sign. The position of the second multiplication sign should be spaced from the first position, so the starting position should be the first multiplication sign position + 2, up to 48, which is the last operator. We will find two The expressions are the same except for the position of the multiplication sign, and the expression equal to 2015 can be subtracted from the expression equal to 1225.

Code:

#include<iostream>
using namespace std;
int main()
{
	for(int i=1;i<=46;i++)
		for (int j = i + 2; j <= 48; j++)
		{
			if (i * (i + 1) - (i + i + 1) + j * (j + 1) - (j + j + 1) == 2015 - 1225)
			{
				cout << i << " " << j << endl;
			}
	 }
	return 0;
}

Answer: 16

7. Number of card types (fill in the blank)

Xiao Ming was hijacked to X Casino and forced to play cards with 3 other people. A deck of playing cards (excluding the big and small trump cards, a total of 52 cards) is evenly distributed to 4 people, each with 13 cards. At this time, a question suddenly popped into Xiao Ming's mind: If you don't consider the suit, only the points, and the order of the cards you get, how many initial card combinations can you get in your hand?

Please fill in the whole number without any superfluous content or explanatory text.

 Idea: By analyzing the question, we can know that this question is actually a permutation and combination problem. We need to try all the possibilities of permutation and combination solutions. According to this feature, we can use recursion to solve it (the possibility that recursion can be searched), but this question has a limitation. It only considers the number of points and does not consider the order of the cards, so when solving, it cannot be calculated as different solutions for different sorting methods like solving the full arrangement. In fact, this problem can be converted to solve the number of occurrences of each number . Avoid the problem that the cards are counted in different order, and sometimes a different way of thinking about the problem may make the problem easier to deal with.

Code:

#include <iostream>
#define ll long long
using namespace std;
ll ans = 0;
void dfs(int cnt, int num) {
	//拿到十三张牌
	if (cnt == 13) ans++;
	//牌的数量超过十三张
	if (cnt >= 13) return;
	//拿到第十四种牌 (当然是不允许的)
	if (num > 13) return;
	//遍历第num种牌的拿取方式 
	for (int i = 0; i <= 4; i++) {
		dfs(cnt + i, num + 1);
	}
}
int main() {

	dfs(0, 1);
	cout << ans << endl;
	return 0;
}

Answer: 3598180

8. Moving distance (programming question)

The buildings in Planet X's residential community are all the same and arranged in a matrix pattern. The number of its buildings is 1, 2, 3...
When a row is full, the numbers are arranged in the opposite direction from the adjacent buildings in the next row.
For example: when the cell row number width is 6, the starting situation is as follows:

1 2 3 4 5 6
12 11 10 9 8 7
13 14 15 …

Our problem is: Knowing two building numbers m and n, we need to find the shortest moving distance between them (can't move diagonally)

The input is 3 integers wmn, separated by spaces, all in the range of 1 to 10000,
w is the row number width, m, n are the building numbers to be calculated.
It is required to output an integer representing the shortest moving distance between the two floors of mn.

For example:
user input:
6 8 2
then the program should output:
4

Another example:
user input:
4 7 20
, the program should output:
5

Resource convention:
peak memory consumption < 256M
CPU consumption < 1000ms

Please output strictly according to the requirements, and do not superficially print superfluous content like: "Please enter...".

All code is placed in the same source file, after debugging, copy and submit the source code.

Note: The main function needs to return 0
Note: Only use the ANSI C/ANSI C++ standard, do not call special functions that depend on the compilation environment or operating system.
Note: All dependent functions must be explicitly #included in the source file, and common header files cannot be omitted through project settings.

When submitting, take care to select the desired compiler type.

Ideas: This question is to test some mathematical formulas. First, calculate the row where the two numbers m and n are located. How to calculate the sac? It is m%w, n%w, judge whether it is equal to 0, if it is equal to 0, then the number of rows is equal to rm=m/w, rn=n/w, if not equal to 0, then rm=m/w+1, rn=n /w+1; The second is to determine the number of columns, because they are arranged in the opposite direction, first determine whether it is in an even column or an odd column rm%2 If it is in an even column, it is rm*w-m+1 This itself Bring in a few numbers until the cause, if not in the odd column w-(rm*wm); the same is true for rn.

#include<iostream>
using namespace std;
int main()
{
	int w, m, n;
	cin >> w >> m >> n;
	int rm = m % w == 0 ? m / w : m / w + 1;
	int rn = n % w == 0 ? n / w : n / w + 1;
	int cn = 0, cm = 0;
	if (rm % 2 == 0)cm = rm * w - m + 1;
	else
		cm = w - (rm * w - m);
	if (rn % 2 == 0) cn = rn * w - n + 1;
	else
		cn = w - (rn * w - n);
	cout << abs(rm - rn) + abs(cm - cn) << endl;
	return 0;
}

9. Rolling dice (programming questions)

The gambling saint atm fell in love with the dice in his later years, that is, the dice are stacked one on top of the other.
After a long period of observation, atm discovered the mystery of stable dice: some numbers face each other repel each other!
Let's standardize the dice first: the opposite of a 1 is a 4, the opposite of a 2 is a 5, and the opposite of a 3 is a 6.
Assuming that there are m groups of mutually exclusive phenomena, the faces of the two numbers in each group are close to each other, and the dice cannot be stably stacked.
atm wants to count how many different possible ways to roll the dice.
The two ways of laying dice are the same if and only if the corresponding numbers of the dice of corresponding heights in both ways are facing the same.
Since the number of solutions may be too many, please output the result modulo 10^9 + 7.

Don't underestimate the number of dice at ATM~

"Input format"
The first line of two integers nm
n represents the number of dice
, the next m lines, each line of two integers ab, indicating that a and b numbers can not be closely together.

"Output format" is
one number per line, indicating the result of the answer modulo 10^9 + 7.

"Sample Input"
2 1
1 2

"Sample output"
544

"Data Range"
For 30% of the data: n <= 5
For 60% of the data: n <= 100
For 100% of the data: 0 < n <= 10^9, m <= 36

Resource convention:
peak memory consumption < 256M
CPU consumption < 2000ms

Please output strictly according to the requirements, and do not superficially print superfluous content like: "Please enter...".

All code is placed in the same source file, after debugging, copy and submit the source code.

Note: The main function needs to return 0
Note: Only use the ANSI C/ANSI C++ standard, do not call special functions that depend on the compilation environment or operating system.
Note: All dependent functions must be explicitly #included in the source file, and common header files cannot be omitted through project settings.

When submitting, take care to select the desired compiler type. 

Ideas: We can use recursion and dynamic programming to do this problem, but we can only get partial points. The important thing is to understand these two ideas. We will use the matrix to solve this problem later.

Method 1: Recursion

//递归
#include<iostream>
using namespace std;
#define mod 1000000007
int op[7];//记录对立面
bool  conflict[7][7];//判断是否冲突
int n, m;
void Init()
{
	op[1] = 4;
	op[2] = 5;
	op[3] = 6;
	op[4] = 1;
	op[5] = 2;
	op[6] = 3;
}
long long int  f(int up, int cnt)
{
	if (cnt == 0)
	{
		return 4;
	}
	long long ants = 0;
	for (int upp = 1; upp <= 6; upp++)
	{
		if (conflict[op[up]][upp])continue;
		ants = (ants + f(upp, cnt - 1)) % mod;
	}
	return ants;
}
int main()
{
	Init();
	cin >> n >> m;
	int x, y;
	long long ants = 0;
	for (int i = 0; i < m; i++)
	{
		cin >> x >> y;
		conflict[x][y] = true;
		conflict[y][x] = true;
	}
	for (int up = 1; up <= 6; up++)
	{
		ants = (ants + 4*f(up, n - 1))%mod;
	}
	cout << ants << endl;
	return 0;
}

Method 2: Dynamic Programming

#include<iostream>
#include<map>
using namespace std;
long long dp[2][7];//dp[i][j]表示有i层,限定朝上的数字为j的稳定方案数
#define mod 1000000007
//int op[7];//记录对立面
bool  conflict[7][7];//判断是否冲突
map<int, int>op;
int n, m;
void Init()
{
	op[1] = 4;
	op[2] = 5;
	op[3] = 6;
	op[4] = 1;
	op[5] = 2;
	op[6] = 3;
}
int main()
{
	Init();
	cin >> n >> m;
	int x, y;
	long long ants = 0;
	for (int i = 0; i < m; i++)
	{
		cin >> x >> y;
		conflict[x][y] = true;
		conflict[y][x] = true;
	}
	//输入完成
	for (int j = 1; j <= 6; j++)
	{
		dp[0][j] = 1;
	}
	int cur = 0;
	//迭代层数
	for (int level = 2; level <= n; level++)
	{
		cur = 1 - cur;
		//尝试把6个面放在当前一层朝上的方向
		for (int j = 1; j <= 6; j++)
		{
			dp[cur][j] = 0;
			//将与op[j]不冲突的上一层格子里面的数累加起来
			for (int i = 1; i <= 6; i++)
			{
				if (conflict[op[j]][i])continue;//冲突的面朝上是不可取的
					dp[cur][j] = (dp[cur][j] + dp[1 - cur][i]) % mod;
			}
		}
	}
	long long sum = 0;
		for (int k = 1; k <= 6; k++)
		{
			sum = (sum + dp[cur][k] )% mod;
		}
	//快速冥求4的次方
	long long ans = 1;
	long long tmp = 4;
	long long p = n;
	while (p != 0)
	{
		if (p & 1 == 1) ans = (ans * tmp) % mod;
		tmp = (tmp * tmp) % mod;
		p >>= 1;
	}
	cout << (sum * ans) % mod << endl;
			return 0;
}

 Method 3: Matrix

#include<bits/stdc++.h>
#define ag(x) ((x)>3?(x)-3:(x)+3)
using namespace std;
typedef long long ll;
ll mod=1e9+7; 
struct matrix{
	int n,m;
	ll s[10][10];
};
//对A的初始化修改成 初始化为4,因为骰子四个面可以互相转动,需要最终乘以4或者初始化为4
matrix Aunit(matrix A){
	for(int i=0;i<6;i++){
		for(int j=0;j<6;j++){
			A.s[i][j]=4;
		}
	}
	return A;
}
//返回一个单位矩阵
matrix unit(matrix A){
	matrix re;
	re.n=A.n;re.m=A.m;
	for(int i=0;i<re.n;i++){
		for(int j=0;j<re.m;j++){
			if(i==j)re.s[i][j]=1;
			else re.s[i][j]=0;
		}
	}
	return re;
}
//两个矩阵相乘
matrix mix(matrix A,matrix B){
	matrix re;re.n=A.n;re.m=B.m;
	for(int i=0;i<re.n;i++){
		for(int j=0;j<re.m;j++){
			re.s[i][j]=0;
			for(int k=0;k<A.m;k++){
			    re.s[i][j]+=A.s[i][k]*B.s[k][j]%mod;
			    re.s[i][j]%=mod;
			}
		}
	}
	return re;
}
//快速求 矩阵A的b次方
matrix dpow(matrix A,ll b){
    matrix re;
	re=unit(A);
	while(b){
		if(b&1)re=mix(re,A);
		A=mix(A,A);
		b>>=1;
	}
	return re;
}
int main(){
	ll n,m;
    scanf("%lld%lld",&n,&m);
    matrix A;A.n=6;A.m=6;
	A=Aunit(A); //初始化矩阵A,表示冲突矩阵
	int ip1,ip2;
	//设置冲突矩阵的冲突面(两两对应)
	while(m--){
		scanf("%d%d",&ip1,&ip2);
		A.s[ip2-1][ag(ip1)-1]=0;
		A.s[ip1-1][ag(ip2)-1]=0;
	}
	matrix p;p.n=1;p.m=6;
	for(int j=0;j<6;j++)p.s[0][j]=4;
	A=dpow(A,n-1); //求A矩阵的n-1次方
    p=mix(p,A); //最后算A^n-1矩阵 * p矩阵,(p就是高度为1的第一个矩阵对应dp[1])
    ll ans=0;
    for(int j=0;j<6;j++)ans=(ans+p.s[0][j])%mod;
	printf("%lld\n",ans);
	return 0;
}

10. The Tree of Life (Programming Question)

In the X forest, God created the tree of life. He marked each node (the leaf is also called a node) of each tree with an integer representing the harmony value of this point. God wants to select a non-empty node set S in this tree, so that for any two points a, b in S, there is a point list {a, v1, v2, ..., vk, b} such that Each point in this point list is an element in S, and there is an edge between two adjacent points in the sequence. 
Under this premise, God wants to make the sum of the integers corresponding to the points in S as large as possible. This greatest sum is God's score for the tree of life.  
After atm's efforts, he already knew the integers that God gave to every node on every tree. But since the atm is not good at calculations, he doesn't know how to get the score efficiently. He needs you to write a program for him to calculate the score of a tree.   
An integer n in the first line of the "input format" 
indicates that the tree has n nodes. The second line contains n integers, which in turn represent the score of each node. 
Next n-1 lines, each line contains 2 integers u, v, indicating that there is an edge from u to v. Since this is a tree, there are no cycles.   
The "Output Format" 
outputs a line with a number, indicating the score that God gave the tree.   
"Sample Input" 


1 -2 -3 4 5

4 2

3 1

1 2

2 5   
"Sample Output"

 8   
"Data range" 
For 30% of the data, n <= 10 
For 100% of the data, 0 < n <= 10^5, the absolute value of the score of each node does not exceed 10^6.   
Resource convention: 
peak memory consumption < 256M CPU consumption < 3000ms

Idea: There are 2 kinds of decisions for each node, which are to choose and not to choose, then we define dp[ i ][ 0 ] and dp[ i ][ 1 ] respectively to indicate that not choosing (selecting) i node can get The maximum weight sum of . The state transition equation is: dp [ i ] [ 1 ] = sum(max(dp[ j ][ 1 ] , dp[ j ][ 0 ])); j is the child of i ; dp[ i ][ 0 ] = 0; Since the title given is an unrooted tree, it is necessary to mark it when performing DFS. When the child nodes of the node to be searched have been visited, then it is a leaf node. It is also on the recursive boundary (stops the search for this branch).

#include<cstdio>
#include<cstring>
#include<vector>
#define N 100005
using namespace std;
vector<int> node[N];
// dp[i][0],dp[i][1];
// 分别表示选i结点和不选能得到的最大分数 
int dp[N][2];
int v[N],vis[N];
int n,a,b;
void dfs(int u){
	dp[u][1] = v[u];
	dp[u][0] = 0;
	vis[u]=1;
	for(int i=0 ;i<node[u].size();i++){
		if(!vis[node[u][i]]){
			dfs(node[u][i]);
	
			dp[u][1] += max(dp[node[u][i]][1],dp[node[u][i]][0]);
		
		}else{
			dp[u][1] = max(dp[u][1],v[u]);
			dp[u][0] = max(dp[u][0],0);
		}
	}
} 
 
void init(){
	memset(v,0,sizeof(v));
	memset(dp,0,sizeof(dp));
	scanf("%d",&n);
	for(int i=1 ;i<=n ;i++){
		scanf("%d",&v[i]);
	}
	for(int i=1 ;i<n ;i++){
		scanf("%d%d",&a,&b);
		node[a].push_back(b);
		node[b].push_back(a);
	}
}
 
int main(){
	init();
	
	dfs(1);
	int ans = -1;
	for(int i=1 ;i<=n ;i++){
//		printf("dp[%d][1]:%d\n",i,dp[i][1]);
//		printf("dp[%d][0]:%d\n",i,dp[i][0]);
		ans = max(ans,dp[i][1]);
		ans = max(ans,dp[i][0]);
	}
	printf("%d\n",ans);
	return 0;
} 

11. Summary

1. Enumeration of the number of lottery tickets           + string search

2.  Simple calculation of galaxy bomb             

3. Sanyang Xianrui               enumeration + judgment, mathematical reasoning to reduce unknowns

4. The output of %*s in the grid            requires two parameters: width and output content

5.  Recursive total permutation of nine groups of fractions         

6. Addition to multiplication           enumeration, clever calculation

7. Recursion of the number of card types               

8. Move distance              to find the symbolic formula by example

9. Base Dice                  Matrix Operations

10. The infinite tree of the tree of life            has the number of roots, DFS, and maintains the maximum weight and sum that can be obtained when each node is used as a root

Guess you like

Origin blog.csdn.net/m0_58367586/article/details/123727457