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
自己想了许久还是有错误,但是自己举例测试(K=1,K=0,K=N)都没问题,不知为何。还有一点N=10000时不出意外地超时。。
以下是我写的巨丑代码
</pre><pre name="code" class="cpp">#include <stdio.h>
#include <vector>
#include <stdlib.h>
#include <algorithm>
struct Case
{
int address;
int data;
int next;
};
int Order(std::vector<Case>& vec, int Address, int N);
void print(std::vector<Case>& List, int N, int K);
int main()
{
int Address;
int N, K;
scanf("%d %d %d", &Address, &N, &K);
std::vector<Case> List(N + 2);
for (int i = 0; i < N; i++) {
scanf("%d %d %d", &List[i].address, &List[i].data, &List[i].next);
}
int n = Order(List, Address, N);
print(List, N, K);
//system("pause");
return 0;
}
int Order(std::vector<Case>& List, int Address, int N)
{
std::vector<Case> vec(N + 2);
int i, j = 1, k;
for (i = 0; i < N; i++) {
if (List[i].address == Address){
vec[0] = List[i];
break;
}
}
while (List[i].next != -1) {
for (k = 0; k < N; k++) {
if (List[k].address == List[i].next) {
vec[j++] = List[k];
break;
}
}
i = k;
}
vec[j] = List[i];
List = vec;
return j ;
}
void print(std::vector<Case>& List, int N, int K)
{
int a;
if ((K == 0)||(K == 1)) {
for (a = 0; a < N - 1; a++){
printf("%05d %d %05d\n", List[a].address, List[a].data, List[a+1].address);
}
printf("%05d %d -1\n", List[a].address, List[a].data);
return;
}
else if (K == N) {
for (a = N - 1; a >= 0; a--){
printf("%05d %d %05d\n", List[a].address, List[a].data, List[a + 1].address);
}
printf("%05d %d -1\n", List[a].address, List[a].data);
return;
}
int count = K, x = N / K; int i = 0, j = 0;
while (x--) {
j += (K - 1);
i = j;
while (count--) {
if ((((N / K - 1)* K ) == i) && (N %K == 0)) {
printf("%05d %d -1\n", List[i].address, List[i].data);
return;
}
printf("%05d %d %05d\n", List[i].address, List[i].data, List[i + 1].address);
i--;
}
count = K;
j++;
}
if (N % K != 0){
for (j; j < N - 1; j++) {
printf("%05d %d %05d\n", List[j].address, List[j].data, List[j + 1].address);
}
printf("%05d %d -1\n", List[j].address, List[j].data);
return;
}
}
后来百度了一下,找了个最短的,同样用STL,为啥差距这么大呢?
仔细考虑了一下,下述代码有两点比较巧妙的地方。
(1)将元素地址作为数组下标,便于后面的排序。而我直接将元素存入数组,导致每次排序都要讲剩余元素浏览一遍。
(2)reverse函数进行倒序,然后打印。避免了打印时要考虑的许多细节。
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
#define MAXN 100001
typedef struct{
int addr;
int data;
int next;
}Node;
Node nodes[MAXN];
vector<Node> list;
int main(){
int firstAdd, n, k;
scanf("%d%d%d", &firstAdd, &n, &k);
while (n--){
Node nn;
scanf("%d%d%d", &nn.addr, &nn.data, &nn.next);
nodes[nn.addr] = nn;//storage
}
int address = firstAdd;
while (address != -1){//sort
list.push_back(nodes[address]);
address = nodes[address].next;
}
int length = list.size();
int round = length / k;
for (int i = 1; i <= round; ++i){//reverse
int start = (i - 1)*k;
int end = i*k;
reverse(list.begin() + start, list.begin() + end);
}
for (int i = 0; i < length - 1; ++i){
printf("%05d %d %05d\n", list[i].addr, list[i].data, list[i + 1].addr);//print
}
printf("%05d %d %d\n", list[length - 1].addr, list[length - 1].data, -1);
return 0;
}
自己改了一下,这次只有超时,看来还是数据结构的问题,每排一个元素都要遍历数组太费时间了。
不过以地址作为下标的方法确实。。
#include <stdio.h>
#include <vector>
#include <stdlib.h>
#include <algorithm>
struct Case
{
int address;
int data;
int next;
};
int Order(std::vector<Case>& vec, int Address, int N);
//void print(std::vector<Case>& List, int N, int K);
int main()
{
int Address;
int N, K;
scanf("%d %d %d", &Address, &N, &K);
std::vector<Case> List(N + 2);
for (int i = 0; i < N; i++) {
scanf("%d %d %d", &List[i].address, &List[i].data, &List[i].next);
}
int n = Order(List, Address, N);
//print(List, N, K);
int length = n;
int round = length / K;
for (int i = 1; i <= round; ++i){//reverse
int start = (i - 1)*K;
int end = i*K;
reverse(std::begin(List) + start, std::begin(List) + end);
}
for (int i = 0; i < length - 1; ++i){
printf("%05d %d %05d\n", List[i].address, List[i].data, List[i + 1].address);//print
}
printf("%05d %d %d\n", List[length - 1].address, List[length - 1].data, -1);
//system("pause");
return 0;
}
int Order(std::vector<Case>& List, int Address, int N)
{
std::vector<Case> vec(N + 2);
int i, j = 1, k;
for (i = 0; i < N; i++) {
if (List[i].address == Address){
vec[0] = List[i];
break;
}
}
while (List[i].next != -1) {
for (k = 0; k < N; k++) {
if (List[k].address == List[i].next) {
vec[j++] = List[k];
break;
}
}
i = k;
}
vec[j] = List[i];
List = vec;
return j ;
}