算法分析 - 期末总结

1、 汉诺塔

汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#define ll long long
const int maxn = 200005;
const int INF = 0x3f3f3f3f;

void move(int n, char a, char b, char c)
{
    if(n == 1)
    {
        printf("%c --> %c\n", a, c);
    }
    else
    {
        move(n - 1, a, c, b);          //将前n-1个圆盘从柱a移动到柱b
        printf("%c --> %c\n", a, c);   //将第n个圆盘从柱a移动到柱c
        move(n -1, b, a, c);           //将柱b中的n-1个圆盘从柱b移动到柱c
    }
}

int main() {
	int n;
    cout << "输入圆盘数:";
	cin >> n;
    move(n,'a','b','c');
    cout << "共需要:" << pow(2,n) - 1 << "次" << endl;
    // dp[n] = dp[n-1] * 2 + 1;
}

2、 插入排序

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#define ll long long
const int maxn = 200005;
const int INF = 0x3f3f3f3f;

int cnt = 0;

void Pri(int a[],int s) {
	for(int i = 0; i < s; ++i) {
		printf("%d ", a[i]);
	}
	printf("\n");
	return;
}

void Insert_Sort(int a[],int s) {
	for(int i = 1; i < s; ++i) {
		int t = a[i];
		int j = i - 1;
		while(j >= 0 && a[j] > t) {
			a[j+1] = a[j];
			--j;
		}
		a[j+1] = t;
		++cnt;
	}
	return;
}

int main() {
	int a[1005],s;
	cin >> s;
	for(int i = 0; i < s; ++i) {
		cin >> a[i];
	}
	Insert_Sort(a,s);
	Pri(a,s);
	cout << "基本操作执行次数:" << cnt << endl;
	return 0;
}

3、 斐波拉契数列

#include <iostream>
#include <cstdio>
using namespace std;
#define ll long long
const int maxn = 200005;
const int INF = 0x3f3f3f;

int counting=0;

int fib(int n){
    if(n <= 1) return n;
    counting++;
    return fib(n-1) + fib(n-2);
}

int main(){
    fib(7);
    cout << "the number of add poeration in fib(7)is:" << counting << endl;
    return 0;
}

4、 八皇后

#include <iostream>
#include <cstdio>
using namespace std;
#define ll long long
const int maxn = 200005;
const int INF = 0x3f3f3f;

int n,a[50],ans = 0;
bool vis[3][50];
int cnt = 0;

void dfs(int i) {
    ++cnt;
    if(i == n+1) {
        ++ans;
        for(int _i = 1; _i <= n; ++_i){
            cout << "(" << _i << "," << a[_i] << ") ";
        }
        cout << endl;
        return;
    }
    for(int j = 1; j <= n; ++j)
        if(!vis[0][j] && !vis[1][j+i] && !vis[2][j-i+n]) {
            a[i] = j;
            vis[0][j] = 1; //第j列是否有棋子
            vis[1][j+i] = 1; //"/"的对角线是否有棋子
            vis[2][j-i+n] = 1; //"\"的对角线是否有棋子
            dfs(i+1);
            vis[0][j] = 0;
            vis[1][j+i] = 0;
            vis[2][j-i+n] = 0;
        }
    return;
}

int main() {
    cout << "输入n: ";
    cin >> n;
    dfs(1);
    cout << "共有" << ans << "种解法" << endl;
    cout << "基本操作执行次数:" << cnt << endl;
    return 0;
}

int main() {
    cout << "输入n: ";
    cin >> n;
    dfs(1);
    cout << "共有" << ans << "种解法" << endl;
    cout << "基本操作执行次数:" << cnt << endl;
    return 0;
}

5、平面最近点对

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn = 10000 * 2 + 5;
const int INF = 0x3f3f3f3f;

struct Node {
    double x,y;
}n[1005];

double dis(Node a, Node b) {
    return sqrt((a.x-b.x) * (a.x-b.x) + (a.y-b.y) * (a.y-b.y));
}

bool cmp(Node a, Node b) {
    if(a.x == b.x) return a.y < b.y;
    else return a.x < b.x;
}

double fun(int l, int r) {
    if(l + 1 == r) {
        return dis(n[l],n[r]);
    }
    else if(l + 2 == r) {
        return min(dis(n[l],n[r]),min(dis(n[l],n[l+1]),dis(n[l+1],n[r])));
    }
    int mid = (l + r) / 2;
    double d = min(fun(l,mid),fun(mid+1,r));
    for(int i = max(mid-(int)d,l); i <= mid; ++i) {
        for(int j = mid+1; j <= min(mid+(int)d+1,r); ++j) {
            if(i != j) d = min(d, dis(n[i],n[j]));
        }
    }
    return d;
}

int main() {
    int cnt = 0;
    cin >> cnt;
    for(int i = 0; i < cnt; ++i) {
        cin >> n[i].x >> n[i].y;
    }
    //枚举法求解
    double _ans = (double)INF;
    for(int i = 0; i < cnt; ++i) {
        for(int j = 0; j < cnt; ++j) {
            if(i != j) {
                double t = dis(n[i],n[j]);
                _ans = min(_ans, t);
            }
        }
    }
    //分治法求解
    //将数组按x从小到大排序
    sort(n,n+cnt,cmp);
    double ans = fun(0, cnt-1);
    cout << "分治算法求解: " << ans << endl;
    cout << "枚举法求解:   " << _ans << endl;
    return 0;
}

6、凸包问题

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn = 10000 * 2 + 5;
const int INF = 0x3f3f3f3f;

struct Node {
    double x,y;
};

Node n[maxn] = {0};
Node sta[maxn] = {0};

double dis(Node a, Node b) {
    return sqrt((a.x-b.x) * (a.x-b.x) + (a.y-b.y) * (a.y-b.y));
}

double judge(Node a, Node b, Node o) {
    return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
}

bool cmp(Node a, Node b) {
    Node o = n[0];
    double t = judge(a, b, o);
    if(t == 0) return dis(a, o) < dis(b, o);
    else return t > 0;
}

int fun(int cnt) {
    //点集中左下角的点作为凸包起始点,放在n[0]的位置
    int t = 0;
    for(int i = 1; i < cnt; ++i) {
        if(n[t].y > n[i].y || (n[i].y == n[t].y && n[t].x > n[i].x)) {
            t = i;
        }
    }
    swap(n[0],n[t]);
    //按极角大小排序,(小的在前)
    //如果极角相等的话就按距离远近排序,(近的在前)
    sort(n+1,n+cnt,cmp);
    //维护一个凸集合栈
    int top = 0;
    sta[top] = n[0];
    for(int i = 1; i < cnt; ++i) {
        while(top > 0 && judge(sta[top-1], n[i], sta[top]) >= 0) {
            --top;
        }
        sta[++top] = n[i];
    }
    return top;
}

int main() {
    int cnt;
    cin >> cnt;
    for(int i = 0; i < cnt; ++i) {
        cin >> n[i].x >> n[i].y;
    }
    int top = fun(cnt);
    cout << "凸包点对: " << endl;
    for(int i = 0; i <= top; ++i) {
        cout << sta[i].x << " , " << sta[i].y << endl;
    }
    return 0;
}

7.分支界限求解背包问题

#include <iostream>
#include <cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define ll long long
const int maxn = 205;
const int INF = 0x3f3f3f;

struct node
{
    int cv, lv;
    int lc;
    int id;
    int ans[maxn];//解向量
    node()
    {
        for(int i = 0; i < maxn; ++i) 
            ans[i] = 0;
    }
    node(int current_value, int left_value, int left_capacity, int _id)
    {
        for(int i = 0; i < maxn; ++i) 
            ans[i] = 0;
        cv = current_value;
        lv = left_value;
        lc = left_capacity;
        id = _id;
    }
};

int n, cap; //物品个数,背包容量
int w[maxn], v[maxn]; //物品重量和价值
int _ans[maxn]; //结果
int _v; //价值

void _init_()
{
    memset(w, 0, sizeof(w));
    memset(v, 0, sizeof(v));
    memset(_ans, 0, sizeof(_ans));
    _v = 0;
}

void bfs()
{
    queue<node> q;
    int sum_v = 0;
    for (int i = 0; i < n; ++i)
        sum_v += v[i];
    q.push(node(0, sum_v, cap, 0));
    while (!q.empty())
    {
        node u;
        u = q.front(); q.pop();
        int _id = u.id;
        if (_id > n || u.lc == 0) //到达叶子结点或者没有容量了
        {
            if (u.cv >= _v)
            {
                for (int i = 0; i < n; ++i)
                    _ans[i] = u.ans[i];  
                _v = u.cv;
            }
            continue;
        }
        if (u.cv + u.lv < _v) //当前状态可到达最大价值小于当前已到达最大价值
            continue;
        if (u.lc >= w[_id]) //加入u物品,生成左孩子
        {
            node lchild(u.cv + v[_id], u.lv - v[_id], u.lc - w[_id], _id + 1);
            for (int i = 0; i < n; ++i)
                lchild.ans[i] = u.ans[i];
            lchild.ans[_id] = 1;
            if (lchild.cv > _v)
                _v = lchild.cv;
            q.push(lchild);
        }
        if (u.cv + u.lv - v[_id] >= _v) //不加入u物品,生成右孩子
        {
            node rchild(u.cv, u.lv - v[_id], u.lc, _id + 1);
            for (int i = 0; i < n; ++i)
                rchild.ans[i] = u.ans[i];
            rchild.ans[_id] = 0;
            q.push(rchild);
        }
    }
}

int main()
{
    _init_();
    cout << "请输入物品数量:" << endl;
    cin >> n;
    cout << "请输入背包容量:" << endl;
    cin >> cap;
    cout << "请依次输入物品的重量和价值:" << endl;
    for (int i = 0; i < n; ++i)
        cin >> w[i] >> v[i];
    bfs();
    cout << "可装载物品的最大价值为:" << _v << endl;
    cout << "装入的物品为:";
    for (int i = 0; i < n; ++i)
        if (_ans[i])
            cout << i << " ";
    cout << endl;
    return 0;
}

8.逆序数

#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long
const int maxn = 1e6+5;
using namespace std;
struct node {
    ll val, num;
}a[maxn];
ll n, ans = 0, t[maxn];
void add(ll x,ll k) {
    for(ll i = x; i <= n; i += i&(-i)) t[i] += k;
}
ll query(ll x) {
    ll sum=0;
    for(ll i = x; i ; i -= i&(-i)) sum += t[i];
    return sum;
}
bool cmp(node x, node y) {
    if(x.val == y.val) return x.num > y.num;
    return x.val > y.val;
}
int main() {
    scanf("%lld", &n);
    for(ll i = 1; i <= n; i++) {
        scanf("%lld", &a[i].val);
        a[i].num = i;
    }
    sort(a+1, a+n+1, cmp);
    for(ll i = 1; i <= n; i++) {
        add(a[i].num, 1);
        ans += query(a[i].num-1);
    }
    printf("%lld\n", ans);
}

9.求第k小问题

// 求第k小
#include<iostream>
#include<algorithm>
using namespace std;

int Partion(int* A, int left, int right)
{
    int key = A[right];
    int i = left - 1;
    for (int j = left; j <= right - 1; j++)
    {
        if (A[j] < key)
        {
            i++;
            swap(A[i], A[j]);
        }
    }
    swap(A[i + 1], A[right]);
    return i + 1;
}

int select_k(int* A, int left, int right, int k)
{
    if (left == right)
    {
        return A[left];
    }
    //使用冒泡排序选择用于划分的主元
    int p = Partion(A, left, right);
    int i = p - left + 1;
    if (k == i)
    {
        return A[p];
    }
    if (k < i)
    {
        return select_k(A, left, p - 1, k);
    }
    if (k > i)
    {
        return select_k(A, p + 1, right, k - i);
    }
return 0;
}

int main()
{
    cout << "请输入数列长度:";
    int n, a[100], k;
    cin >> n;
    cout << "请输入数列:" << endl;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    cout << "请输入要查找的元素位数: ";
    cin >> k;
    cout << "第k小的元素为:" << select_k(a, 0, n - 1, k);
}

10.最大子段和

#include<iostream>
using namespace std;

int Max_sum(int a[], int left, int right)
{
    int sum = 0;
    if (left == right)
    {
        if (a[left] > 0) sum = a[left];
        else sum = 0;
    }
    else
    {
        int mid = (left + right) / 2;
        int leftsum = Max_sum(a, left, mid);
        int rightsum = Max_sum(a, mid + 1, right);
        int s_left = 0, left_ = 0;
        for (int i = mid; i >= left; i--)
        {
            left_ += a[i];
            if (left_ > s_left)
                s_left = left_;
        }
        int s_right = 0, right_ = 0;
        for (int i = mid + 1; i <= right; i++)
        {
            right_ += a[i];
            if (right_ > s_right)
                s_right = right_;
        }
        sum = s_left + s_right;
        if (sum < leftsum) sum = leftsum;
        if (sum < rightsum) sum = rightsum;

    }
    return sum;
}

int main()
{
    cout << "请输入数列长度:";
    int n, a[100];
    cin >> n;
    cout << "请输入数列:" << endl;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    cout << "最大字段和为:" << Max_sum(a, 0, n - 1);
}

11.找零问题

#include<iostream>
#include<cmath>
using namespace std;

int n, v[10] = {0};
int money = 0;
int dp[100] = {0};

int main() {
    // 输入钱币有几种面值
    cin >> n;
    // 输入各钱币面值
    for(int i = 0; i < n; ++i)
        cin >> v[i];
    // 输入目标价钱
    cin >> money;
    for(int i = 1; i <= money; ++i) {
        dp[i] = i;
        for(int j = 0; j < n; ++j){
            if(v[j] <= i) {
                dp[i] = min(dp[i], dp[i-v[j]]+1);
            }
        }
    }
    cout << dp[money] << endl;
}

12.0-1背包问题

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 10005;
const int INF = 0x3f3f3f3f;
//dp[i][j]表示从前i件物品们中选择放入容量为j的背包的最大价值
int dp[maxn][maxn] = {0};
int w[maxn] = {0}, v[maxn] = {0};
int n, c;
int main() {
    //物品数量和背包容量
    cin >> n >> c;
    //每个物品的重量和价值
    for (int i = 1; i <= n; ++i)
        cin >> w[i];
    for (int i = 1; i <= n; ++i)
        cin >> v[i];
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= c; j++) {
            if (j < w[i]) dp[i][j] = dp[i - 1][j];
            else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);
        }
    }
    printf("%d\n",dp[n][c]);
}

13.二分查找

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
#define ll long long
const int maxn = 200005;
const int INF = 0x3f3f3f3f;

int a[maxn] = {0};
int n = 0,x = 0;

int binarySearch(int nums[], int target) {
    int left = 0; 
    int right = n - 3; 
    while(left <= right) {
        for(int i = left; i <= right; ++i) printf("%d ",nums[i]);
            printf("\n");
        if(target >= nums[left] && target <= nums[right]){
            int mid = (right + left) / 2;
            if(nums[mid] == target)
                return mid; 
            else if (nums[mid] < target)
                left = mid + 1; 
            else if (nums[mid] > target)
                right = mid - 1; 
        }
        else
            return -1;
    }
    return -1;
}

int main() {
    while(scanf("%d",&a[n++]) != EOF) {};
    x = binarySearch(a, a[n-2]);
    printf("%d\n", x+1);
}

14.最短路径问题

#include <cstdio>
#include <iostream>
#include <stack>
using namespace std;

const int maxn = 105;
const int INF = 0x3f3f3f3f;
struct Node{
    int x = 0,y = 0;
};

int m,n;
int map[maxn][maxn] = {0};
Node b[maxn][maxn];
int dp[maxn][maxn] = {0};
int main() {
    cin >> m >> n;
    for(int i = 0; i < m; ++i) {
        for(int j = 0; j < n; ++j) {
            cin >> map[i][j];
            dp[i][j] = INF;
        }
    }
    dp[0][0] = map[0][0];
    for(int i = 0; i < m; ++i) {
        for(int j = 0; j < n; ++j) {
            if(i-1 >= 0 && dp[i][j] > dp[i-1][j] + map[i][j]) {
                dp[i][j] = dp[i-1][j] + map[i][j];
                b[i][j].x = i-1;
                b[i][j].y = j; 
            }
            if(j-1 >= 0 && dp[i][j] > dp[i][j-1] + map[i][j]) {
                dp[i][j] = dp[i][j-1] + map[i][j];
                b[i][j].x = i;
                b[i][j].y = j-1; 
            }
            //cout <<"("<< i << "," << j <<"): " << dp[i][j] << endl;
        }
    }
    cout << dp[m-1][n-1] << endl;
    stack<Node> sta;
    Node n1; n1.x = m-1, n1.y = n-1;
    while(!(n1.x == 0 && n1.y == 0)) {
        Node nt;
        nt.x = n1.x+1;
        nt.y = n1.y+1;
        sta.push(nt);
        n1.x = b[nt.x-1][nt.y-1].x;
        n1.y = b[nt.x-1][nt.y-1].y;
    }
    cout << 1 << " " << 1 << endl;
    while(!sta.empty()) {
        Node nt = sta.top();
        sta.pop();
        cout << nt.x << " " << nt.y << endl;
    }
    return 0;
}

15.01背包(动态规划)

#include <cstdio>
#include <iostream>
#include <stack>
using namespace std;

const int maxn = 10005;
const int INF = 0x3f3f3f3f;
int dp[maxn][maxn] = {0};
int b[maxn][maxn] = {0};
int w[maxn] = {0}, v[maxn] = {0};
int n, c;

int main() {
    cin >> c >> n;
    for (int i = 1; i <= n; ++i)
        cin >> v[i];
    for (int i = 1; i <= n; ++i)
        cin >> w[i];
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j <= c; ++j) {
            dp[i][j] = dp[i - 1][j];
            b[i][j] = -1;
            if(j >= w[i] && dp[i - 1][j - w[i]] + v[i] > dp[i - 1][j]) {
                dp[i][j] = dp[i - 1][j - w[i]] + v[i];
                b[i][j] = i;
            }
        }
    }
    cout << dp[n][c] << endl;
    int jj = c,ii = n;
    stack<int> sta;
    while(dp[ii][jj] > 0){
        if(b[ii][jj] != -1) {
            sta.push(b[ii][jj]);
            jj = jj - w[b[ii][jj]];
        }
        ii = ii - 1;
    }
    while(!sta.empty()) {
        cout << sta.top() << " ";
        sta.pop();
    }
}

16、最长公共子序列

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;

char a[1005],b[1005];
char at[1005],bt[1005];
int dp[1005][1005],l1,l2;

void LCS(int i,int j) {
	for(i = 1; i <= l1; ++i) {
		for(j = 1; j <= l2; ++j) {
			if(a[i-1] == b[j-1]) {
				dp[i][j] = dp[i-1][j-1] + 1;
			}
			else if(dp[i-1][j] > dp[i][j-1]) {
				dp[i][j] = dp[i-1][j];
			}
			else {
				dp[i][j] = dp[i][j-1];
			}
		}
	}
}

int cnt = 0;

void fun() {
	int i = 0,j = 0,z = 0;
	char c[1005];
	memset(c,0,sizeof(c));
	i = l1, j = l2;
	while(i != 0 && j != 0) {
		if(a[i-1] == b[j-1]) {
			c[z++] = a[--i];
			j--;
		}
		else if(dp[i-1][j] < dp[i][j-1]){
			j--;
		}
		else if(dp[i][j-1] <= dp[i-1][j]) {
			i--;
		}
	}
	printf("%d\n",z);
	if(z == 0) {
		printf("None\n");	
	}
	else {
		for(i = z-1; i >= 0; i--) {
			printf("%c",c[i]);
		}
		printf("\n");
	}
}

int main() {
	string at,bt;
	getline(cin,at);
	getline(cin,bt);
	int l1t = 0;
	int l2t = 0;
	for(int i = 0; i <= at.length(); ++i) {
		if(at[i] != ' ') {
			a[l1t++] = at[i];
		}
	}
	for(int i = 0; i <= bt.length(); ++i) {
		if(at[i] != ' ') {
			b[l2t++] = bt[i];
		}
	}
	//cout << a << endl;
	//cout << b << endl;
	memset(dp,0,sizeof(dp));
	l1 = strlen(a);
	l2 = strlen(b);
	LCS(l1,l2);
	fun();
	return 0;
}


17、最大子段和

#include<iostream>
using namespace std;
int b[100]={0};
int a[100]={0};
int d[100]={0};
int v[100]={0};
int n;
int sum;
int max(int a,int b){
	if(a>b)
		return a;
	else return b;
}
void maxlength(){
	int i;
	for(i=1;i<=n;i++){
		if(b[i-1]>0){
			b[i]=b[i-1]+a[i];
			d[i]=1;
			}
		else b[i]=a[i];
		if(b[i]>sum){
			sum=b[i]; 
			v[i]=1;
		}
	}
	cout<<sum<<endl;
}
int main(){
	n=1;
	int k,j;
	while(cin>>a[n]){
		if(getchar()=='\n')
			break;
		n++;
	}
	maxlength();
	for(int i=n;i>=1;i--){
		if(b[i]==sum&&v[i]){
			j=i;
			break;
		}	
	} 
	for(int i=j;i>=1;i--){
		if(d[i]==0){
			k=i;
			break;
		}
	}
	cout<<k<<endl<<j;		
}

18.动态规划算法解矩阵连乘

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>

using namespace std;

int m[105][105] = {0}, s[105][105] = {0};

void Mat(int *p,int n)
{
	for(int i = 1; i <= n; ++i)
		m[i][i]=0;
	for(int r = 2; r <= n; ++r)
	{
		for(int i = 1; i <= n-r+1; ++i) 
		{
			int j = i+r-1;
			s[i][j] = i;
			m[i][j] = m[i][i] + m[i+1][j] + p[i-1]*p[i]*p[j];
			for(int k = i+1; k < j; ++k)
			{
				int t = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
				if(t < m[i][j])
				{
					s[i][j] = k;
					m[i][j] = t;
				}
			}
		} 
	}
	printf("%d\n",m[1][n]);
} 

void Tra(int i,int j)
{
	if(i==j)
		printf("A%d",i);
	else
	{
		printf("("); 
		Tra(i,s[i][j]);
		Tra(s[i][j]+1,j);
		printf(")");
	}
}

int main()
{
	int a[105] = {0};
	int n = 0, l = -1;
	while(scanf("%d", &n) != EOF)
	{
		a[++l] = n;
	}
	Mat(a, l);
	Tra(1, l); 
}


19.棋盘覆盖问题

#include<iostream>
using namespace std;
int map[100][100]={0};
int n;
int t1=1;
void chessboard(int dr,int dc,int tr,int tc,int size){
	if(size==1)
		return ;
	int t=t1++;
	int s=size/2;
	if(dr<tr+s&&dc<tc+s)
		chessboard(dr,dc,tr,tc,s);
	else{
		map[tr+s-1][tc+s-1]=t;
		chessboard(tr+s-1,tc+s-1,tr,tc,s);
	}
	if(dr<tr+s&&dc>=tc+s)
		chessboard(dr,dc,tr,tc+s,s);
	else{
		map[tr+s-1][tc+s]=t;
		chessboard(tr+s-1,tc+s,tr,tc+s,s);
	}
	if(dr>=tr+s&&dc<tc+s)
		chessboard(dr,dc,tr+s,tc,s);
	else{
		map[tr+s][tc+s-1]=t;
		chessboard(tr+s,tc+s-1,tr+s,tc,s);
	}
	if(dr>=tr+s&&dc>=tc+s)
		chessboard(dr,dc,tr+s,tc+s,s);
	else{
		map[tr+s][tc+s]=t;
		chessboard(tr+s,tc+s,tr+s,tc+s,s);
	}	
}
int main(){
	int x,y;
	int s=1;
	cin>>n>>x>>y;
	for(int i=1;i<=n;i++)
		s=s*2;
	map[x][y]=-1;
	chessboard(x,y,1,1,s);
	for(int i=1;i<=s;i++){
		for(int j=1;j<=s;j++)
			cout<<map[i][j]<<" ";
			cout<<endl;
	}
		return 0;
}

20.全排列问题

#include<iostream>
using namespace std;
int n;
int s[100]={0};

int pd[100]={0};
int answer[100]={0};
void print(){
	for(int i=0;i<n;i++)
		printf("%d ",answer[i]);
	printf("\n"); 
}
void dfs(int k){
	if(k==n){
		print();
		return ;
	}
	for(int i=0;i<n;i++){
		if(!pd[i]){
		pd[i]=1;
		answer[k]=s[i];
		dfs(k+1);
		pd[i]=0;
	    }
	}	
}
int main(){
	int k=0;
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>s[i];
	dfs(0);
	return 0;
}

21.线性时间内寻找元素

#include<iostream>
using namespace std;
int b[100];
int c=0;
void fun(int a[],int p,int r)
{
	for(int i=p;i<=r;i++)
	cout<<a[i]<<" ";
	cout<<endl;
}
void swap(int *a,int *b)
{
	int temp;
	temp=*a;
	*a=*b;
	*b=temp;
}
int partition(int a[],int p,int r,int jz)
{
	int i=p-1;
	for(int j=p;j<=r-1;j++)
	{
		if(a[j]<=jz)
		{
			i++;
			swap(a[i],a[j]);
		}
	}
	swap(a[i+1],a[r]);
	return i+1;
 } 
void Sort(int a[],int p,int r)
{
	for(int i=p;i<r;i++)
	{
		for(int j=i+1;j<=r;j++)
		if(a[j]<a[i])
		swap(a[i],a[j]);
	}
}

int select(int a[],int p,int r,int k)
{
	if(r-p<5)
	{
		Sort(a,p,r);

		return a[p+k-1];
	}
	for(int i=0;i<=(r-p-4)/5;i++)
	{
		int s=p+i*5,t=s+4;
		Sort(a,s,t);

		swap(a[p+i],a[s+2]);

	}
    int	x=select(a,p,p+(r-p-4)/5,(r-p-4)/10+1);
    b[c++]=x;
	int i=partition(a,p,r,x);

	int j=i-p+1;
	if(k<=j)
	return select(a,p,i,k);
	else
	return select(a,i+1,r,k-j);
}
int main()
{
	int a[100];
	int k=0,o;
	while(cin>>o)
	{
		a[k++]=o;
		if(cin.get()=='\n')
		break;
	}

	int m;
	cin>>m;
	
	int con=select(a,0,k-1,m);
	cout<<b[0]<<endl;
	Sort(a,0,k-1);
	cout<<a[m-1];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值