1053. Path of Equal Weight (30)

1.题目给出一棵和一个权重值W,要求求出从根到叶子节点权重累加为W的路径。

2.该题使用树节点数据结构,其中包含vector<int> child列表和权重值。

3.使用DFS进行遍历搜索(节点最多100个),能够满足要求。

1053

时间限制
10 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Given a non-empty tree with root R, and with weight Wi assigned to each tree node Ti. The weight of a path from R to L is defined to be the sum of the weights of all the nodes along the path from R to any leaf node L.

Now given any weighted tree, you are supposed to find all the paths with their weights equal to a given number. For example, let’s consider the tree showed in Figure 1: for each node, the upper number is the node ID which is a two-digit number, and the lower number is the weight of that node. Suppose that the given number is 24, then there exists 4 different paths which have the same given weight: {10 5 2 7}, {10 4 10}, {10 3 3 6 2} and {10 3 3 6 2}, which correspond to the red edges in Figure 1.

1053说明
Figure 1
Input Specification:

Each input file contains one test case. Each case starts with a line containing 0 < N <= 100, the number of nodes in a tree, M (< N), the number of non-leaf nodes, and 0 < S < 230, the given weight number. The next line contains N positive numbers where Wi (<1000) corresponds to the tree node Ti. Then M lines follow, each in the format:

ID K ID[1] ID[2] ... ID[K]

where ID is a two-digit number representing a given non-leaf node, K is the number of its children, followed by a sequence of two-digit ID’s of its children. For the sake of simplicity, let us fix the root ID to be 00.

Output Specification:

For each test case, print all the paths with weight S in non-increasing order. Each path occupies a line with printed weights from the root to the leaf in order. All the numbers must be separated by a space with no extra space at the end of the line.

Note: sequence {A1, A2, …, An} is said to be greater than sequence {B1, B2, …, Bm} if there exists 1 <= k < min{n, m} such that Ai = Bifor i=1, … k, and Ak+1 > Bk+1.

Sample Input:

20 9 24
10 2 4 3 5 10 2 18 9 7 2 2 1 3 12 1 8 6 2 2
00 4 01 02 03 04
02 1 05
04 2 06 07
03 3 11 12 13
06 1 09
07 2 08 10
16 1 15
13 3 14 16 17
17 2 18 19

Sample Output:

10 5 2 7
10 4 10
10 3 3 6 2
10 3 3 6 2

 
AC代码:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;
struct TreeNode{
	vector<int> child;
	int w;
	TreeNode() :child(0), w(0){};
};
void dfs(int now, int target, vector<TreeNode>&tree, vector<int>&path, vector<vector<int>>&ans)
{
	if (tree[now].child.size() == 0 && target == 0)
		ans.push_back(path);//叶子节点,并且满足要求
	if (tree[now].child.size() != 0 && target <= 0)
		return;//
	else if (target < 0)
		return;
	for (int i = 0; i < tree[now].child.size(); i++)
	{
		path.push_back(tree[tree[now].child[i]].w);
		dfs(tree[now].child[i], target - tree[tree[now].child[i]].w, tree, path, ans);
		path.pop_back();
	}
}
bool cmp(const vector<int>&a, const vector<int>&b)
{
	for (int i = 0; i < min(a.size(), b.size()); i++)
	{
		if (a[i] >b[i])
			return true;
		else if (a[i] < b[i])
			return false;
	}
	return false;
}
int main(void)
{
	int nodeSum, nonLeafSum, target;
	cin >> nodeSum >> nonLeafSum >> target;
	vector<TreeNode> tree(nodeSum);
	
	for (int i = 0; i < nodeSum; i++)
	{
		scanf("%d", &tree[i].w);
	}

	for (int i = 0; i < nonLeafSum; i++)
	{
		int nodeNum=0;
		scanf("%d", &nodeNum);
		int childSum = 0;
		scanf("%d", &childSum);
		tree[nodeNum].child = vector<int>(childSum);
		for (int j = 0; j < childSum; j++)
		{
			scanf("%d", &tree[nodeNum].child[j]);
		}
	}
	if (nodeSum > 0)
	{
		vector<int> path;
		vector<vector<int>> ans;
		path.push_back(tree[0].w);//注意判断根节点是否存在
		target -= tree[0].w;
		dfs(0, target, tree, path, ans);
		sort(ans.begin(), ans.end(), cmp);
		for (int i = 0; i < ans.size(); i++)
		{
			for (int j = 0; j < ans[i].size(); j++)
			{
				printf("%d", ans[i][j]);
				if (j != ans[i].size() - 1)
					printf(" ");
			}
			printf("\n");
		}

	}
	return 0;
}

1052. Linked List Sorting (25)

1.题目给出一些节点和其连接的下一个节点地址,求出sort后的链表。

2.这道题目主要有两个难点

1)以head为头部的链表不一样包括全部n个,即输入的数据中存在多个链表,但是我们只需要对以head为头部的链表排序输出即可,这也是为什么结果要求我们输出排序后的链表大小,因为这个大小不一定和n相等;

2)head为-1的情况,卡在这里比较久,需要特殊判断,然后输出0 -1

3.采用建立链表,然后拷贝到vector上进行排序输出。

1052

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

A linked list consists of a series of structures, which are not necessarily adjacent in memory. We assume that each structure contains an integer key and a Next pointer to the next structure. Now given a linked list, you are supposed to sort the structures according to their key values in increasing order.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive N (< 105) and an address of the head node, where N is the total number of nodes in memory and the address of a node is a 5-digit positive integer. NULL is represented by -1.

Then N lines follow, each describes a node in the format:

Address Key Next

where Address is the address of the node in memory, Key is an integer in [-105, 105], and Next is the address of the next node. It is guaranteed that all the keys are distinct and there is no cycle in the linked list starting from the head node.

Output Specification:

For each test case, the output format is the same as that of the input, where N is the total number of nodes in the list and all the nodes must be sorted order.

Sample Input:

5 00001
11111 100 -1
00001 0 22222
33333 100000 11111
12345 -1 33333
22222 1000 12345

Sample Output:

5 12345
12345 -1 00001
00001 0 11111
11111 100 22222
22222 1000 33333
33333 100000 -1

AC代码:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;
struct ListNode{
	int val, add;
	ListNode*next;
	ListNode() :val(0), add(0), next(NULL){};
	ListNode(int x) :val(x), add(0), next(NULL){};
};
bool cmp(const ListNode&a, const ListNode&b)
{
	return a.val < b.val;
}
int main(void)
{//链表可能断开,需要用头部所在的链表进行排序
	int n, head;
	cin >> n >> head;
	vector<ListNode> list(100001);
	for (int i = 0; i < n; i++)
	{//读取数据
		int now, val, next;
		scanf("%d %d %d", &now, &val, &next);

		list[now].add = now;//保存地址
		list[now].val = val;//保存val
		if (next != -1)
		{//如果next不为-1,则有节点
			list[now].next = &list[next];//进行连接
			list[next].add = next;//记录next的地址
		}
	}
	vector<ListNode> listOrder(0);//建立一个新的vector
	if (head != -1)
	{
		ListNode* root = &list[head];//记录头部
		while (root)//遍历这个链表
		{
			listOrder.push_back(*root);//压入节点
			root = root->next;
		}
		sort(listOrder.begin(), listOrder.end(), cmp);

		printf("%d %05d\n", listOrder.size(), listOrder[0].add);
		for (int i = 0; i < listOrder.size(); i++)
		{
			printf("%05d %d ", listOrder[i].add, listOrder[i].val);
			if (i != listOrder.size() - 1)
				printf("%05d\n", listOrder[i + 1].add);
			else
				printf("-1\n");
		}
	}
	else//需要对head==-1进行处理,最后一个测试点考察这个
		printf("%d -1\n", listOrder.size());


	return 0;
}

1051. Pop Sequence (25)

1.这道题是判断出栈队列是否合理。

2.采用了用栈来模拟情况。

3.当目前栈为空,或者栈不为空并且栈顶不等于目标值,并且队列中还有数值可以压入,栈的size小于最大容量,那么就一直循环执行压入操作,把123456789。。。队列中的值依次压入栈,直到跳出循环。

4.跳出循环后,判断栈顶是否等于目标值,不等于的话,这个sequence就是不合理的,如果等于,则把栈顶的值pop掉,再执行步骤3。

1051

时间限制
100 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Given a stack which can keep M numbers at most. Push N numbers in the order of 1, 2, 3, …, N and pop randomly. You are supposed to tell if a given sequence of numbers is a possible pop sequence of the stack. For example, if M is 5 and N is 7, we can obtain 1, 2, 3, 4, 5, 6, 7 from the stack, but not 3, 2, 1, 7, 5, 6, 4.

Input Specification:

Each input file contains one test case. For each case, the first line contains 3 numbers (all no more than 1000): M (the maximum capacity of the stack), N (the length of push sequence), and K (the number of pop sequences to be checked). Then K lines follow, each contains a pop sequence of N numbers. All the numbers in a line are separated by a space.

Output Specification:

For each pop sequence, print in one line “YES” if it is indeed a possible pop sequence of the stack, or “NO” if not.

Sample Input:

5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2

Sample Output:

YES
NO
NO
YES
NO

 
AC代码:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;

int main(void)
{
	int maxCap, maxSequence, querySum;
	cin >> maxCap >> maxSequence >> querySum;
	for (int k = 0; k < querySum; k++)
	{
		int idx = 1;
		stack<int> sta;
		int maxNum = maxCap;//栈里面能够存在的最大的值
		vector<int> sequence(maxSequence);
		for (int i = 0; i < maxSequence; i++)
			scanf("%d", &sequence[i]);
		bool result = true;

		for (int i = 0; i < maxSequence; i++)
		{

			if (sequence[i]>maxNum)
			{//不合理
				result = false;
				break;
			}
			while ((sta.empty() || (!sta.empty() && sta.top() != sequence[i])) && idx <= maxSequence && sta.size() <= maxCap)
			{// 如果栈为空,或者栈不为空但是头部不等于目标值,并且还有值可以压入,队列size小于最大容量
				sta.push(idx++);
			}
			if (sta.top() != sequence[i])
			{//如果经过上面的压入操作后,仍不满足要求,则不合理
				result = false;
				break;
			}
			sta.pop();
			maxNum++;//弹出了一个,可以压入更大的一个值

		}
		if (result)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	return 0;
}

1050. String Subtraction (20)

1.给出两个string,下面string中包含的字符,需要在上面的string中删除。

2.这道题需要注意,s1和s2的输入都需要使用getline,避免出现空格的情况。

时间限制
10 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Given two strings S1 and S2, S = S1 – S2 is defined to be the remaining string after taking all the characters in S2 from S1. Your task is simply to calculate S1 – S2 for any given strings. However, it might not be that simple to do it fast.

Input Specification:

Each input file contains one test case. Each case consists of two lines which gives S1 and S2, respectively. The string lengths of both strings are no more than 104. It is guaranteed that all the characters are visible ASCII codes and white space, and a new line character signals the end of a string.

Output Specification:

For each test case, print S1 – S2 in one line.

Sample Input:

They are students.
aeiou

Sample Output:

Thy r stdnts.

 
AC代码:

//#include<string>
//#include <iomanip>
#include<vector>
#include <algorithm>
//#include<stack>
#include<set>
#include<queue>
#include<map>
//#include<unordered_set>
#include<unordered_map>
//#include <sstream>
//#include "func.h"
//#include <list>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
using namespace std;

int main(void)
{

	string s1, s2;
	getline(cin, s1);
	getline(cin, s2);//注意s2也需要geline,可能包括空格
	bool exist[256] = { 0 };
	for (int i = 0; i<s2.size(); i++)
	{
		exist[s2[i]] = true;
	}
	string ans = "";
	for (int i = 0; i<s1.size(); i++)
	{
		if (!exist[s1[i]])
			ans += s1[i];
	}
	cout << ans << endl;
	return 0;
}

1049. Counting Ones (30)

1.和leetcode里面的Number of Digit One一样,统计0~n中,出现多少个1.

2.算法说明:

如3141592,在m(digitDivide)=100时,即要求计算百位上“1”的个数

其中a为31415,b为92,31415中出现了3142次“1”,因为每10个数里面出现1次“1”。而实际上,31415是3141500,所以把31415中1的个数再乘以m。如3141400~3141499中,前缀为31414的数出现了100次,所以需要乘以m(此时是100)。

时间限制
10 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

The task is simple: given any positive integer N, you are supposed to count the total number of 1’s in the decimal form of the integers from 1 to N. For example, given N being 12, there are five 1’s in 1, 10, 11, and 12.

Input Specification:

Each input file contains one test case which gives the positive N (<=230).

Output Specification:

For each test case, print the number of 1’s in one line.

Sample Input:

12

Sample Output:

5

AC代码:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <stack>
#include <algorithm>
#include <memory.h>
#include <map>
#include <set>
#include "limits.h"
using namespace std;


int main(void)
{
    long long n;
    cin>>n;
	long long ans = 0;
    for(long long digitDivide=1;digitDivide<=n;digitDivide*=10)
    {
		long long a = n / digitDivide;
		long long b = n%digitDivide;
        ans+=(a+8)/10*digitDivide+(a%10==1)*(b+1);
    }
    cout<<ans<<endl;
    
    return 0;
}

 

1048. Find Coins (25)

1.和leetcode的two sum一样,找出两个coin,使其价值等于amount。

2.采用哈希表记录已经遍历过的数据,target=pay-num[i],查找num[target]是否在哈希表中有,如果有,则压进ans容器,最后进行排序输出。

3.时间复杂度为o(n)。

1048find coins

 

时间限制
50 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special requirement of the payment: for each bill, she could only use exactly two coins to pay the exact amount. Since she has as many as 105 coins with her, she definitely needs your help. You are supposed to tell her, for any given amount of money, whether or not she can find two coins to pay for it.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive numbers: N (<=105, the total number of coins) and M(<=103, the amount of money Eva has to pay). The second line contains N face values of the coins, which are all positive numbers no more than 500. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the two face values V1 and V2 (separated by a space) such that V1 + V2 = M and V1 <= V2. If such a solution is not unique, output the one with the smallest V1. If there is no solution, output “No Solution” instead.

Sample Input 1:

8 15
1 2 8 7 2 4 11 15

Sample Output 1:

4 11

Sample Input 2:

7 14
1 8 7 2 4 11 15

Sample Output 2:

No Solution

 

AC代码如下:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <stack>
#include <algorithm>
#include <memory.h>
#include <map>
#include <set>
#include "limits.h"
using namespace std;
/*
 8 15 
 1 2 8 7 2 4 11 15
 
 
 7 14
 1 8 7 2 4 11 15
 */
bool cmp(const pair<int,int>&a,const pair<int,int>&b)
{
    return a.first<b.first;
}

int main(void)
{
    int coinSum,pay;
    scanf("%d %d",&coinSum,&pay);
    int *coin=new int[coinSum];
    int target;
    int *haveCoin=new int[501];
    memset(haveCoin, 0, sizeof(haveCoin));
    vector<pair<int,int>> ans(0);
    for(int i=0;i<coinSum;i++)
    {
        scanf("%d",&coin[i]);
        target=pay-coin[i];
        if(target>=0&&target<=500&&haveCoin[target]>0)
        {
            int a=min(coin[i],target);
            int b=pay-a;
            ans.push_back({a,b});
        }
        haveCoin[coin[i]]++;
    }
    sort(ans.begin(),ans.end(),cmp);
    if(ans.size()>0)
        printf("%d %d\n",ans[0].first,ans[0].second);
    else
        printf("No Solution\n");
    return 0;
}

1047. Student List for Course (25)

1.和前面的1039 Course List for Student (25) 相类似,但是这次给出学生选的课程数,求每个课程有多少学生选,分别是谁。

2.刚开始使用vector<set<int>> 格式存储course,后面在输入数据的时候就已经超时。

3.随后改为vector<vector<int>> 存储,在后面进行sort,没有超时。

时间限制
400 ms
内存限制
64000 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Zhejiang University has 40000 students and provides 2500 courses. Now given the registered course list of each student, you are supposed to output the student name lists of all the courses.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 numbers: N (<=40000), the total number of students, and K (<=2500), the total number of courses. Then N lines follow, each contains a student’s name (3 capital English letters plus a one-digit number), a positive number C (<=20) which is the number of courses that this student has registered, and then followed by C course numbers. For the sake of simplicity, the courses are numbered from 1 to K.

Output Specification:

For each test case, print the student name lists of all the courses in increasing order of the course numbers. For each course, first print in one line the course number and the number of registered students, separated by a space. Then output the students’ names in alphabetical order. Each name occupies a line.

Sample Input:

10 5
ZOE1 2 4 5
ANN0 3 5 2 1
BOB5 5 3 4 2 1 5
JOE4 1 2
JAY9 4 1 2 5 4
FRA8 3 4 2 5
DON2 2 4 5
AMY7 1 5
KAT3 3 5 4 2
LOR6 4 2 4 1 5

Sample Output:

1 4
ANN0
BOB5
JAY9
LOR6
2 7
ANN0
BOB5
FRA8
JAY9
JOE4
KAT3
LOR6
3 1
BOB5
4 7
BOB5
DON2
FRA8
JAY9
KAT3
LOR6
ZOE1
5 9
AMY7
ANN0
BOB5
DON2
FRA8
JAY9
KAT3
LOR6
ZOE1

 

AC代码如下:

//#include<string>
//#include <iomanip>
#include<vector>
#include <algorithm>
//#include<stack>
#include<set>
#include<queue>
#include<map>
//#include<unordered_set>
#include<unordered_map>
//#include <sstream>
//#include "func.h"
//#include <list>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
using namespace std;

int main(void)
{
	int studentSum, courseSum;
	scanf("%d %d", &studentSum, &courseSum);
	char name[5];
	vector<vector<int>> course(courseSum);
	int *courseIdx = new int[20];
	int nameInt;
	int chooseSum;
	for (int i = 0; i<studentSum; i++)
	{//输入学生即其所选的课程
		scanf("%s", name);
		nameInt = (name[0] - 'A') * 26 * 26 * 10 + (name[1] - 'A') * 26 * 10 + (name[2] - 'A') * 10 + (name[3] - '0');
		scanf("%d", &chooseSum);
		for (int j = 0; j<chooseSum; j++)
		{
			scanf("%d", &courseIdx[j]);
			course[courseIdx[j] - 1].push_back(nameInt);
		}
	}
	for (int i = 0; i<course.size(); i++)
	{//输出各门课程的结果
		printf("%d %d\n", i + 1, course[i].size());
		sort(course[i].begin(), course[i].end());
		for (vector<int>::iterator ite = course[i].begin(); ite != course[i].end(); ite++)
		{//转化学生的名字,进行输出
			name[4] = 0;
			name[3] = (*ite) % 10 + '0';
			name[2] = ((*ite) / 10) % 26 + 'A';
			name[1] = ((*ite) / 10 / 26) % 26 + 'A';
			name[0] = ((*ite) / 10 / 26 / 26) + 'A';
			printf("%s\n", name);
		}
	}

	return 0;
}

1046. Shortest Distance (20)

1.给出一个数组,求出0到i点的最短距离,可以直接从0->1->2->…->i,也可以0->n-1->n-2->n-3->…->i+1->i。

2.建立一个数组dp[i],记录0到i之间的距离和。

3.定义sum,记录全程的路程。

4.求i,j的最短距离时,利用ans=dp[j]-[i]+num[i]-num[j],ans2=sum-ans,min(ans,ans2)即为答案。

时间限制
100 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.

Input Specification:

Each input file contains one test case. For each case, the first line contains an integer N (in [3, 105]), followed by N integer distances D1 D2 … DN, where Di is the distance between the i-th and the (i+1)-st exits, and DN is between the N-th and the 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M (<=104), with M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 to N. It is guaranteed that the total round trip distance is no more than 107.

Output Specification:

For each test case, print your results in M lines, each contains the shortest distance between the corresponding given pair of exits.

Sample Input:

5 1 2 4 14 9
3
1 3
2 5
4 1

Sample Output:

3
10
7

AC代码:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <stack>
#include <algorithm>
#include <memory.h>
#include <map>
#include <set>
#include "limits.h"
using namespace std;

int main(void)
{
    
    int n;
    scanf("%d",&n);
    int *num=new int[n];
    int *dp=new int[n];
    memset(dp, 0, sizeof(dp));
    int sum=0;
    for(int i=0;i<n;i++)
    {
        scanf("%d",&num[i]);
        if(i==0) dp[i]=num[i];
        else dp[i]=dp[i-1]+num[i];
        sum+=num[i];
    }
    int m;
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d %d",&a,&b);
        if(a>b) swap(a,b);
        int tmp=dp[b-1]-dp[a-1]+num[a-1]-num[b-1];
        int tmp2=sum-tmp;
        printf("%d\n",min(tmp2,tmp));
    }
    return 0;
}

1045. Favorite Color Stripe (30)

1.这个和最长公共子序列问题相类似(LCS),给出目标字符串,求出在t中求出符合顺序和颜色要求的最长子字符串(可以省去目标字符串中的一些颜色)。

2.不同的地方是允许元素重复,如{a}和{aaa},匹配出来的是3,a可以重复3次。

3.该问题一开始卡在了输入格式上。

4.动态规划方程:dp[i][j]表示f[0~i]与o[0~j]匹配的最大长度。

如果f[i]==o[j],dp[i][j]=max(dp[i][j-1]+1,dp[i-1][j-1]),当目前颜色相同,在上一个的基础上+1(表示上一次已经使用f[i]进行匹配),或者在dp[i-1][j-1]上+1(表示这次才开始使用f[i]作为匹配);

如果f[i]!=o[j],dp[i][j]=max(dp[i][j-1],dp[i-1][j]),当目前的颜色不相同,那么选取dp[i][j-1](f[i]已经进行匹配)和dp[i-1][j](f[i]未进行匹配)的最大值。

5.还有一种最简单的方法:dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]),如果f[i]==o[j],则dp[i][j]++:(采用了LCS的思想)

时间限制
200 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Eva is trying to make her own color stripe out of a given one. She would like to keep only her favorite colors in her favorite order by cutting off those unwanted pieces and sewing the remaining parts together to form her favorite color stripe.

It is said that a normal human eye can distinguish about less than 200 different colors, so Eva’s favorite colors are limited. However the original stripe could be very long, and Eva would like to have the remaining favorite stripe with the maximum length. So she needs your help to find her the best result.

Note that the solution might not be unique, but you only have to tell her the maximum length. For example, given a stripe of colors {2 2 4 1 5 5 6 3 1 1 5 6}. If Eva’s favorite colors are given in her favorite order as {2 3 1 5 6}, then she has 4 possible best solutions {2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6}, and {2 2 3 1 1 5 6}.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (<=200) which is the total number of colors involved (and hence the colors are numbered from 1 to N). Then the next line starts with a positive integer M (<=200) followed by M Eva’s favorite color numbers given in her favorite order. Finally the third line starts with a positive integer L (<=10000) which is the length of the given stripe, followed by L colors on the stripe. All the numbers in a line are separated by a space.

Output Specification:

For each test case, simply print in a line the maximum length of Eva’s favorite stripe.

Sample Input:

6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

Sample Output:

7

 
简单方法的AC代码:

//#include<string>
//#include <iomanip>
#include<vector>
#include <algorithm>
//#include<stack>
#include<set>
#include<queue>
#include<map>
//#include<unordered_set>
#include<unordered_map>
//#include <sstream>
//#include "func.h"
//#include <list>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
using namespace std;
/*
6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

6
5 2 3 1 5 6
10 2 2 3 1 3 1 3 1 3 1

6
5 2 3 1 5 6
10
5 6 6 6 6 6 6 6 6 6 6

6
5 2 3 1 5 6
10 
2 6 6 6 6 6 6 6 6 6 6


6
5 2 3 1 5 6
10
2 2 2 6 6 6 6 6 6 6 6

6
5 2 3 1 5 6
10
2 2 2 6 6 6 6 5 6 6 6

6
5 2 3 1 5 6
10
2 2 2 6 6 6 6 6 5 6 6
*/
int main(void)
{
	int colourSum,fnum, onum;
	cin >> colourSum>> fnum;
	vector<int> f(fnum);
	for (int i = 0; i<fnum; i++)
	{
		scanf("%d", &f[i]);
	}
	cin >> onum;
	vector<int> o(onum);

	for (int i = 0; i<onum; i++)
	{
		scanf("%d", &o[i]);
	}

	vector<vector<int>> dp(fnum+1, vector<int>(onum+1,0));

	int thisMax = 0;
	for (int i = 1; i<=f.size(); i++)
	{
		for (int j = 1; j<=o.size(); j++)
		{
			dp[i][j] = max(max(dp[i - 1][j], dp[i][j - 1]), dp[i-1][j-1]);
			if (f[i-1] == o[j-1])
				dp[i][j]++;
		}
	}
	cout << dp[fnum][onum] << endl;
	return 0;
}

第一种方法的AC代码:

//#include<string>
//#include <iomanip>
#include<vector>
#include <algorithm>
//#include<stack>
#include<set>
#include<queue>
#include<map>
//#include<unordered_set>
#include<unordered_map>
//#include <sstream>
//#include "func.h"
//#include <list>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
using namespace std;
/*
6
5 
2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

4
5 
2 3 1 5 6
10 2 2 3 1 3 1 3 1 3 1

2
5 
2 3 1 5 6
10
5 6 6 6 6 6 6 6 6 6 6

2
5 
2 3 1 5 6
10
2 6 6 6 6 6 6 6 6 6 6


2
5 
2 3 1 5 6
10
2 2 2 6 6 6 6 6 6 6 6
*/
int main(void)
{
	int colorSum,fnum, onum;
	cin >> colorSum>> fnum;
	vector<int> f(fnum);
	for (int i = 0; i<fnum; i++)
	{//输入喜欢的颜色
		scanf("%d", &f[i]);
	}
	cin >> onum;
	vector<int> o(onum);

	for (int i = 0; i<onum; i++)
	{//输入源材料
		scanf("%d", &o[i]);
	}

	vector<vector<int>> dp(fnum, vector<int>(onum));
	for (int i = 0; i<f.size(); i++)
	{//初始化边界数组
		if (f[i] == o[0])
			dp[i][0] = 1;
		else if (i == 0)
			dp[i][0] = 0;
		else
			dp[i][0] = dp[i - 1][0];
	}

	for (int i = 0; i<f.size(); i++)
	{
		for (int j = 1; j<o.size(); j++)
		{
			if (f[i] == o[j])
			{//如果相等,那么dp[i][j]由dp[i][j-1]和dp[i-1][j-1]的最大值构成
				if (i != 0)
					dp[i][j] = max(dp[i][j - 1] + 1, dp[i - 1][j - 1] + 1);
				else
					dp[i][j] = dp[i][j - 1] + 1;
			}
			else
			{
				if (i != 0)
					dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);//取包含上一个f的长度和不包含上一个f的长度两者最大值
				else
					dp[i][j] = dp[i][j - 1];
			}
		}
	}
	cout << dp[fnum - 1][onum - 1] << endl;
	return 0;
}

1044. Shopping in Mars (25)

1.题目要求在一个数组中,找出等于amount的连续子序列和,如果不存在等于的,则找出大于amount的最小子序列的和。

2.使用尺取法,如果取得范围总和大于需要pay的,删掉头部。

3.如果取得范围综合小于pay的,增加尾部。

4.注意边界情况和没有相等的情况,细节可查看代码。

5.利用一个minAns的变量进行记录答案数值。

部分测试用例:

16 15
3 2 1 5 4 6 8 7 16 10 15 11 9 12 14 13
 
5 13
2 4 5 7 9
 
 10 1
 2 3 4 5 6 1 2 3 4 6 
 
 10 1
 2 3 4 5 1 1 2 1 1 1
 ans:
 5-5
 6-6
 8-8
 9-9
 10-10
 
 10 0
 2 3 4 5 1 1 2 1 1 1
 ans:
 5-5
 6-6
 8-8
 9-9
 10-10
 
 10 -1
 2 3 4 5 1 1 2 1 1 1
 ans:
 5-5
 6-6
 8-8
 9-9
 10-10
时间限制
100 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Shopping in Mars is quite a different experience. The Mars people pay by chained diamonds. Each diamond has a value (in Mars dollars M$). When making the payment, the chain can be cut at any position for only once and some of the diamonds are taken off the chain one by one. Once a diamond is off the chain, it cannot be taken back. For example, if we have a chain of 8 diamonds with values M$3, 2, 1, 5, 4, 6, 8, 7, and we must pay M$15. We may have 3 options:

1. Cut the chain between 4 and 6, and take off the diamonds from the position 1 to 5 (with values 3+2+1+5+4=15).
2. Cut before 5 or after 6, and take off the diamonds from the position 4 to 6 (with values 5+4+6=15).
3. Cut before 8, and take off the diamonds from the position 7 to 8 (with values 8+7=15).

Now given the chain of diamond values and the amount that a customer has to pay, you are supposed to list all the paying options for the customer.

If it is impossible to pay the exact amount, you must suggest solutions with minimum lost.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 numbers: N (<=105), the total number of diamonds on the chain, and M (<=108), the amount that the customer has to pay. Then the next line contains N positive numbers D1 … DN (Di<=103 for all i=1, …, N) which are the values of the diamonds. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print “i-j” in a line for each pair of i <= j such that Di + … + Dj = M. Note that if there are more than one solution, all the solutions must be printed in increasing order of i.

If there is no solution, output “i-j” for pairs of i <= j such that Di + … + Dj > M with (Di + … + Dj – M) minimized. Again all the solutions must be printed in increasing order of i.

It is guaranteed that the total value of diamonds is sufficient to pay the given amount.

Sample Input 1:

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

Sample Output 1:

1-5
4-6
7-8
11-11

Sample Input 2:

5 13
2 4 5 7 9

Sample Output 2:

2-4
4-5

AC代码:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <stack>
#include <algorithm>
#include <memory.h>
#include <map>
#include <set>
#include "limits.h"
using namespace std;

/*
16 15
3 2 1 5 4 6 8 7 16 10 15 11 9 12 14 13
 
5 13
2 4 5 7 9
 
 10 1
 2 3 4 5 6 1 2 3 4 6 
 
 10 1
 2 3 4 5 1 1 2 1 1 1
 ans:
 5-5
 6-6
 8-8
 9-9
 10-10
 
 10 0
 2 3 4 5 1 1 2 1 1 1
 ans:
 5-5
 6-6
 8-8
 9-9
 10-10
 
 10 -1
 2 3 4 5 1 1 2 1 1 1
 ans:
 5-5
 6-6
 8-8
 9-9
 10-10
 */
bool cmp(const pair<int,pair<int,int>>&a,const pair<int,pair<int,int>>&b)
{
    if(a.first<b.first)
        return true;
    else if(a.first==b.first&&a.second.first<b.second.first)
        return true;
    else return false;
}
int main(void)
{
    int sum,pay;
    scanf("%d %d",&sum,&pay);
    vector<int> diamonds(sum);
    for(int i=0;i<sum;i++)
    {
        scanf("%d",&diamonds[i]);
    }
    int i=0,j=0;
    int value=diamonds[0];//默认输入的数组大于0
    int minAns=INT_MAX;
    vector<pair<int,pair<int,int>>> ans(0);
    while(1)
    {
        if(value==pay&&i<=j)
        {//加入i<=j,避免出现2-1,6-4之类的,j小于i的情况
            minAns=min(minAns,value);
            ans.push_back({value,{i+1,j+1}});
            value-=diamonds[i++];
        }
        else if(value>pay&&i<=j)
        {//加入i<=j,避免出现2-1,6-4之类的,j小于i的情况
            if(value<=minAns)
            {//value>pay && value<=minAns,所以 pay<value<=minAns,minAns>pay
                minAns=value;
                ans.push_back({value,{i+1,j+1}});
            }
            value-=diamonds[i++];
            
        }
        else//value<pay
        {
            j++;
            if(j<diamonds.size())
                value+=diamonds[j];
            else
                break;
        }
    }
    sort(ans.begin(), ans.end(), cmp);
    for(int k=0;k<ans.size();k++)
    {
        if(ans[k].first==minAns)
            printf("%d-%d\n",ans[k].second.first,ans[k].second.second);
        else break;
    }
    
    
    return 0;
}