PTA算法测试题(函数)

0/1背包问题(回溯法)
void dfs(int i,int tw,int tv,int rw,int op[]) {
    if(i > n) {
        if(tw == W && tv > maxv) {
            maxv = tv;
            for(int j = 1; j <= n; j ++ ) x[j] = op[j];
        }
    } else {
        if(tw + w[i] <= W) {
            op[i] = 1;
            dfs(i + 1, tw + w[i], tv + v[i], rw - w[i], op);
        }
        op[i] = 0;
        if(tw + rw > W) dfs(i + 1, tw, tv, rw - w[i], op);
    }
}

快速排序(分治法)
int Partition(SqList &L,int low,int high) {
    L.r[0] = L.r[low];
    int t = L.r[low].key;
    
    while(low < high) {
        while(low < high && L.r[high].key >= t) high --;
        L.r[low] = L.r[high];
        while(low < high && L.r[low].key <= t) low ++ ;
        L.r[high] = L.r[low];
    }
    L.r[low] = L.r[0];
    return low;
    
}

void QSort(SqList &L,int low,int high) {
    if(low < high) {
        int t = Partition(L, low, high);
        QSort(L, low, t - 1);
        QSort(L, t + 1, high);
    }
    
}

棋盘覆盖问题(分治法)
void ChessBoard(int tr,int tc,int dr,int dc,int size) {
    if(size == 1) return;
    
    int s = size / 2;
    int t = tile ++;
    
    if(dr < tr + s && dc < tc + s) ChessBoard(tr, tc, dr, dc, s);
    else {
        board[tr + s - 1][tc + s - 1] = t;
        ChessBoard(tr, tc, tr + s - 1, tc + s - 1, s);
    }
    
    if(dr < tr + s && dc >= tc + s) ChessBoard(tr, tc + s, dr, dc, s);
    else {
        board[tr + s - 1][tc + s] = t;
        ChessBoard(tr, tc + s, tr + s - 1, tc + s, s);
    }
    
    if(dr >= tr + s && dc < tc + s) ChessBoard(tr + s, tc, dr, dc, s);
    else {
        board[tr + s][tc + s - 1] = t;
        ChessBoard(tr + s, tc, tr + s, tc + s - 1, s);
    }
    
    if(dr >= tr + s && dc >= tc + s) ChessBoard(tr + s, tc + s, dr, dc, s);
    else {
        board[tr + s][tc + s] = t;
        ChessBoard(tr + s, tc + s, tr + s, tc + s, s);
    }
}

求解活动安排问题(贪心法)
void solve() {
    sort(A, A + n);
    int t = 0;
    for(int i = 0; i < n; i ++ ) {
        if(A[i].b >= t) {
            flag[i] = true;
            t = A[i].e;
        }
    }
}

最小生成树(克鲁斯卡尔算法)
int p[MVNum];

int find(int x) {
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

void Kruskal(AMGraph G) {
    for(int i = 0; i < G.vexnum; i ++ ) p[i] = i;
    
    for(int k = 0; k < G.arcnum; k ++ ) {
        int min = MaxInt, mini = MaxInt, minj = MaxInt;
        for(int i = 0; i < G.vexnum; i ++ ) {
            for(int j = 0; j < G.vexnum; j ++ ) {
                if(G.arcs[i][j] < min) {
                    min = G.arcs[i][j];
                    mini = i;
                    minj = j;
                }
            }
        }
        int pa = find(mini), pb = find(minj);
        if(pa != pb) {
            p[pa] = pb;
            printf("%d->%d\n", mini, minj);
        }
        G.arcs[mini][minj] = G.arcs[minj][mini] = MaxInt;
    }
}

求解最长递增子序列问题(动态规划法)
void IncreaseOrder(int a[],int dp[],int x[][N],int n) {
    for(int i = 0; i < n; i ++ ) {
        dp[i] = 1;
        x[i][0] = a[i];
        
        int max = 1, maxi = i;
        for(int j = 0; j < i; j ++ ) {
            if(a[j] < a[i] && dp[j] + 1 > max) {
                max = dp[j] + 1;
                maxi = j;
            }
        }
        
        if(maxi != i) {
            dp[i] = max;
            for(int j = 0; j < max - 1; j ++ ) x[i][j] = x[maxi][j];
            x[i][max - 1] = a[i];
        }
    }
}

最短路径(弗洛伊德算法)
void ShortestPath_Floyed(AMGraph G){ 
    int i , j , k ;
    for (i = 0; i < G.vexnum; ++i)
        for(j = 0; j < G.vexnum; ++j){ 
            D[i][j] = G.arcs[i][j];
            if(D[i][j] < MaxInt && i != j) Path[i][j] = i;
            else Path [i][j] = -1; 
        }
    for(k = 0; k < G.vexnum; ++k) 
        for(i = 0; i < G.vexnum; ++i) 
            for(j = 0; j < G.vexnum; ++j)
                if(D[i][k] + D[k][j] < D[i][j]) {
                    D[i][j] = D[i][k] + D[k][j];
                    Path[i][j] = Path[k][j];
                }


}

求解图的m着色问题(回溯法)
void dfs(int i) {
    if(i > n) count ++;
    else {
        for(int j = 1; j <= m; j ++ ) {
            x[i] = j;
            if(Same(i)) dfs(i + 1);
            x[i] = 0;
        }
    }
}

最长递增子序列问题可以用动态规划的方法解决。定义 $dp[i]$ 表示以 $a[i]$ 结尾的最长递增子序列的长度,$x[i][0...dp[i]-1]$ 表示以 $a[i]$ 结尾的最长递增子序列。 则有状态转移方程: $$dp[i]=\max_{0\le j<i}\{dp[j]+1\}(a[j]<a[i])$$ 其中 $\max$ 表示求最大值,$j \in [0,i)$。 同时,需要在状态转移过程中记录下最长递增子序列的具体内容。具体来说,如果 $a[j]<a[i]$ 且 $dp[j]+1=dp[i]$,则 $a[j]$ 是 $a[i]$ 在最长递增子序列中的前一个元素。因此可以通过逆推的方式,从 $dp[index]$ 开始,依次输出每个元素。 完整代码如下: ```c++ #include<bits/stdc++.h> #include<iostream> #define N 100 using namespace std; void IncreaseOrder(int a[], int dp[], int x[][N], int n) { for (int i = 0; i < n; i++) { dp[i] = 1; // 初始化为 1 x[i][0] = a[i]; // 最长递增子序列的起点为自身 for (int j = 0; j < i; j++) { if (a[j] < a[i] && dp[j] + 1 > dp[i]) { // 找到一个 a[j]<a[i] 且 dp[j]+1 最大的 j dp[i] = dp[j] + 1; for (int k = 0; k < dp[j]; k++) { // 复制最长递增子序列 x[i][k] = x[j][k]; } x[i][dp[j]] = a[i]; // 将 a[i] 加到最长递增子序列末尾 } } } } int main() { int A[N], dp[N], X[N][N]; int n, i, index; cin >> n; for (i = 0; i < n; i++) cin >> A[i]; IncreaseOrder(A, dp, X, n); for (index = 0, i = 1; i < n; i++) // 求所有递增子序列的最大长度 if (dp[index] < dp[i]) index = i; cout << dp[index] << endl; // 输出最长递增子序列的长度 for (i = 0; i < dp[index]; i++) // 输出最长递增子序列 cout << X[index][i] << " "; return 0; } ``` 输入样例: ``` 9 2 1 5 3 6 4 8 9 7 ``` 输出样例: ``` 5 1 3 4 8 9 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值