PAT A 1042 1043 1044 1045

1042 模拟

permutation 排列
题目大意: 洗牌 。54张牌的初始序列为[1,...54]。给出每次改变的位置,即将第i个位置的牌挪到第a[i]个位置上。 循环往复。 输出最终的序列。

#include
#include
using namespace std;

char s[5] = {'S','H', 'C', 'D', 'J'};
int k; //k<=20 重复次数
vector v(55), a(55),temp;

void shuchu(){
    for(int i=1;i<=54;i++){
        if( i != 1 ){
            cout<<" ";
        }
        cout<>k;
    for(int i=1;i<=54;i++){
        cin>>v[i];
        a[i] = i;
    } 
    for(int i=1;i<=k;i++){
        temp.clear();
        temp.resize(55);
        for(int i = 1;i<=54;i++){
            temp[v[i]] = a[i];
        }
        for(int i = 1;i<=54;i++){
            a[i] = temp[i];
        }
    }
    shuchu();
    return 0;
}

1043 排序二叉树

题目大意: 已知先序遍历,说明他是排序二叉树还是排序二叉树的镜像(即交换左右子树); 若是 排序二叉树还是排序二叉树的镜像 ,则输出 后序遍历。 若不是,输出NO。
思路:

  • 如果第二个数字小于(大于等于)第一个数字,则推测是排序二叉树(镜像二叉树),因为第二个数字是左孩子,一定比根节点小。(排除递增或者递减序列,这样根本无法判断)。
  • 然后将序列重新排序,因为是排序二叉树,因此中序遍历一定是个递增(递减)序列。找到第一个大于根节点的数字,则是右子树的开始,递归查找左右子树。对于排序二叉树(镜像)来说,若左子树出现大于等于(小于)根节点的值,则输出NO,若右子树出现小于(大于等于)根节点的值,则输出NO。
  • 若输出YES,递归输出后序遍历。值得注意的是,在每次在中序遍历的数组中查找根节点的时候,排序二叉树找的是 第一个 等于 前序遍历的第一个值 得数。镜像二叉树找的是 最后一个 等于 前序遍历的第一个值 得数。

关于一个排序二叉树的小插曲 >>>点击<<<

#include
#include
#include
using namespace std;

int n; //<=1000
vector pre, in, post;
bool flag = true; 
int is = 0;
 
void check1(int root, int end){
    if(root >= end) return;
    int p = root + 1, rst;
    while( p < end && pre[root] <= pre[p] ) p++;
    for(rst = p; p < end; p++){
        if(pre[root] <= pre[p]){
            flag = false;
            return;
        }
    }
    check1(root+1, rst); //检查左
    check1(rst, end); //检查右 
    return;
}

void check2(int root, int end){
    if(root >= end) return;
    int p = root + 1, rst;
    while( p < end && pre[root] > pre[p] ) p++;
    for(rst = p; p < end; p++){
        if(pre[root] > pre[p]){
            flag = false;
            return;
        }
    }
    check2(root+1, rst); //检查左
    check2(rst, end); //检查右 
}

void reverse(int prep,int preq, int inp, int inq){
    if(prep >= preq || inp >= inq) return;
    int inroot;
    for(inroot = inp; inroot < inq; inroot++){
        if(pre[prep] == in[inroot]){
            if(is == 1){ // 如果是镜像,找到相同的值得最后一个 
                for(int i = inroot+1; i>n;
    pre.resize(n);
    in.resize(n);
    for(int i=0;i>pre[i];
    }
    in = pre;
    
    if(pre[0] <= pre[1]){//是镜像 
        is = 1;
        sort(in.begin(), in.end(), greater() ); //从大到小即是中序遍历。
        check1(0,n); 
    }else{
        sort(in.begin(), in.end()); //从小到大即是中序遍历。
        check2(0,n); 
    }
    if(!flag){
        cout<<"NO"<

1044 尺取法

题目大意: 找到所有和为m的连续子序列。若找不到, 找到大于m的最小和 ,输出所有结果。

#include
#include
using namespace std;

typedef struct node{
    int p,q;
}node;

int main(){
    int n, m; // n<=10^5, m<=10^8
    cin>>n>>m;
    vector v(n);
    for(int i=0;i>v[i];
    }
    
    bool flag = false;
    int sum = 0;
    for(int p=0,q=0; p ans;
        int sum = 0, min = 99999999;
        for(int p=0,q=0; p m){
                //cout<

1045 动态规划

题目大意: 给出一串数字A,和一串数字B;想让A中的数字只能是B中的数字的最长子字符串。找最长不下降子字符串。 结果不唯一,只需输出最长的长度。例如:

  • 给出A= {2 2 4 1 5 5 6 3 1 1 5 6}, B= {2 3 1 5 6}。
  • 找出的最长字符串为 {2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6},和{2 2 3 1 1 5 6}。
  • 因此答案为7。

思路: 将每个喜欢的颜色按照输入顺序编号,转化成最长不下降子序列。

#include
#include
#include
using namespace std;
int main(){
    int n, m, x;
    cin>>n>>m; //n<=200,颜色编号从1...n 
    vector fav(n+1); 
    bool visit[205];
    for(int i=1;i<=m;i++){
        cin>>x;
        fav[x] = i; //存入编号 
        visit[x] = true;
    } 
    int l; // l<= 10^4
    cin>>l;
    vector v(l+1);
    int num = 0;
    for(int i=0;i>x;
        if(visit[x] == true){ //剔除不喜欢的 
            v[num++] = fav[x];
        }
    }
    
    //按照最长不下降子序列 
    int dp[10005];
    int ans = 0;
    for(int i = 0; i < num; i++){
        dp[i] = 1;
        for(int j = 0; j < i; j++){
            if(v[i] >= v[j]){
                dp[i] = max(dp[i], dp[j]+1);
            }
        }
        ans = max(dp[i], ans);
    }
    
    cout<

你可能感兴趣的:(PAT A 1042 1043 1044 1045)