算法设计与分析编程题

7-1 最大公约数 (15 分)

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n,x,y,z;
    while(cin >> n)
    {
        while(n --){
            cin >> x >> z;
            int t = x / z;
            for(int i = 2;;i ++){
                if(__gcd(i,t) == 1)
                {
                    cout << i * z << endl;
                    break;
                }
            }
        }
    }
    
    return 0;
}

7-2 查找整数 (10 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10 ;
int a[N];
int main()
{
    int n,x;
    cin >> n >> x;
    
    for(int i = 1,p;i <= n;i ++){
        cin >> p;
        a[p] = i;
    }
    if(a[x]) cout << a[x] - 1 << endl;
    else cout << "Not Found" << endl;
    
    
    return 0;
}

7-3 矩阵A乘以B (15 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[N][N];
int b[N][N];
int c[N][N];

int main()
{
    int ra,ca,rb,cb;
    cin >> ra >> ca;
    for(int i = 1;i <= ra;i ++)
        for(int j = 1;j <= ca;j ++)
            cin >> a[i][j];
    cin >> rb >> cb;
    for(int i = 1;i <= rb;i ++)
        for(int j = 1;j <= cb;j ++)
            cin >> b[i][j];
    
    if(ca != rb){
        printf("Error: %d != %d\n",ca,rb);
    }else{
        
        for(int i = 1;i <= ra;i ++){
            for(int k = 1;k <= cb;k ++){
                int sum = 0;
                for(int j = 1;j <= ca;j ++){
                    sum += a[i][j] * b[j][k];
                }
                c[i][k] = sum;
            }
        }
        
        cout << ra << ' ' << cb << endl;
        
        for(int i = 1;i <= ra;i ++)
        {
            for(int j = 1;j <= cb;j ++){
                if(j == cb){
                    cout << c[i][j];
                    continue;
                }
                cout << c[i][j] << ' ';
            }
            cout << endl;
        }
        
    }
    
    return 0;
}

7-4 IP地址转换 (20 分)

#include <bits/stdc++.h>
using namespace std;


int main()
{
    string str;
    cin >> str;
    string ans;
    vector<int>vec;
    for(int i = 0;i < str.size();i ++){
        ans = ans + str[i];
        if(ans.size() == 8){
            reverse(ans.begin(),ans.end());
            int sum = 0;
            for(int i = 0;i < 8;i ++){
                sum += (1 << i) * (ans[i] - '0');
            }
            vec.push_back(sum);
            ans.clear();
        }
    }
    
    for(int i = 0;i < 4;i ++){
        if(i == 3){
            cout << vec[i];
        }else
            cout << vec[i] << '.';
    }
    
    
    return 0;
}

7-5 汉诺(Hanoi)塔问题 (20 分)

#include <bits/stdc++.h>
using namespace std;
void hanoi(int n,char a,char b,char c)
{
    if(n == 1){
        cout << a << "-->" << c << endl;
    }else{
        
        hanoi(n - 1,a,c,b);
        cout << a << "-->" << c << endl;
        hanoi(n - 1,b,a,c);
    }

    
}
int main()
{
    int n;
    cin >> n;
    char a = 'a',b = 'c',c = 'b';
    hanoi(n,a,b,c);
    return 0;
}

7-6 选择法排序 (20 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 11;
int a[N];
int main()
{
    int n;
    cin >> n;
    for(int i = 0;i < n;i ++)
        cin >> a[i];
    
    sort(a ,a + n);
    reverse(a ,a + n);
    for(int i = 0;i < n;i ++){
        cout << a[i];
        if(i != n - 1) cout << ' ';
    }

    return 0;
}

7-7 选择法排序之过程 (15 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int main()
{
    int n;
    cin >> n;
    for(int i = 0;i < n;i ++)
        cin >> a[i];
    
    if(n == 1){
        cout << a[0] << endl;
        return 0;
    }
    
    for(int i = 0;i < n - 1;i ++){
        int maxn = i;
        for(int j = i;j < n;j ++){
            if(a[j] < a[maxn]){
                maxn = j;
            }
        }
        swap(a[i],a[maxn]);
        
        for(int i = 0;i < n;i ++){
            cout << a[i];
            if(i != n - 1){
                cout << ' ';
            }
        }
        cout << endl;
        
    }
    

    return 0;
}

7-8 冒泡法排序 (20 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int main()
{
    int n,k;
    cin >> n >> k;
    for(int i = 0;i < n;i ++)
        cin >> a[i];
    
    if(n == 1){
        cout << a[0] << endl;
        return 0;
    }
    
    while(k --){
        
        for(int i = 0; i < n - 1;i ++){
            if(a[i] > a[i + 1]){
                swap(a[i],a[i + 1]);
            }
        }
            
    }
    
    for(int i = 0;i < n;i ++){
        cout << a[i];
        if(i != n - 1){
            cout << ' ';
        }
    }

    return 0;
}

7-9 字符串的冒泡排序 (20 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
string a[N];
int main()
{
    int n,k;
    cin >> n >> k;
    for(int i = 0;i < n;i ++)
        cin >> a[i];
    
    if(n == 1){
        cout << a[0] << endl;
        return 0;
    }
    
    while(k --){
        
        for(int i = 0; i < n - 1;i ++){
            if(a[i] > a[i + 1]){
                swap(a[i],a[i + 1]);
            }
        }
            
    }
    
    for(int i = 0;i < n;i ++){
        cout << a[i] << endl;
    }

    return 0;
}

7-10 冒泡法排序之过程 (15 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int main()
{
    int n,k;
    cin >> n;
    for(int i = 0;i < n;i ++)
        cin >> a[i];
    
    if(n == 1){
        cout << a[0] << endl;
        return 0;
    }
    
    for(int j = 0;j < n - 1;j ++){ 
        
        for(int i = 0; i < n - 1;i ++){
            if(a[i] > a[i + 1]){
                swap(a[i],a[i + 1]);
            }
        }
                
        for(int i = 0;i < n;i ++){
            cout << a[i];
            if(i != n - 1){
                cout << ' ';
            }
        }
        cout << endl;
    }


    return 0;
}

7-11 串的模式匹配 (30 分)

  • 字符串hash,kmp也可以做
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef unsigned long long ULL;
ULL P = 131;
char str[N];
ULL h[N], p[N]; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64
// 初始化
// 计算子串 str[l ~ r] 的哈希值
ULL get(int l, int r)
{
    return h[r] - h[l - 1] * p[r - l + 1];
}

char str1[N];
ULL h1[N], p1[N]; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64
// 初始化
// 计算子串 str[l ~ r] 的哈希值
ULL get1(int l, int r)
{
    return h1[r] - h1[l - 1] * p1[r - l + 1];
}

int main()
{
    cin >> str + 1;
    cin >> str1 + 1;
    
    int n = strlen(str + 1);
    int m = strlen(str1 + 1);
    if(n < m) {
        cout << 0 << endl;
        return 0;
    }
    
    p[0] = 1;
    for (int i = 1; i <= n; i ++ )
    {
        h[i] = h[i - 1] * P + str[i];
        p[i] = p[i - 1] * P;
    }
    
    p1[0] = 1;
    
    for (int i = 1; i <= m; i ++ )
    {
        h1[i] = h1[i - 1] * P + str1[i];
        p1[i] = p1[i - 1] * P;
    }
    
    ULL l2 = get1(1,m);
    
    //cout << l2 << ' ' << m << endl;
    for(int i = 1;i <= n - m + 1;i ++){
      //  cout << get(i,i + m - 1) << endl;
        if(get(i,i + m - 1) == l2){
            cout << i << endl;
            return 0;
        }
    }
    
    cout << 0 << endl;
    return 0;
}

7-12 字符串模式匹配 (5 分)

  • 在上面输出ne数组,在下面是不对的
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
char s[N],p[N];
int ne[N]; 
int main()
{
	scanf("%s",s+1);
	scanf("%s",p+1);
	
	int n = strlen(s+1);
	int m = strlen(p+1);
	
	int f = -1;
	printf("%d ",ne[1]-1);
	for (int i = 2 , j = 0 ; i <= m ; i ++ )
	{
		while(j && p[i] != p[j+1]) j = ne[j];
		if(p[i] == p[j+1]) j ++ ;
		ne[i] = j;
		printf("%d ",ne[i]-1);
	}	
	
	for (int i = 1 , j = 0 ; i <= n ; i ++ )
	{
		while(j && s[i] != p[j+1]) j = ne[j];
		if(s[i] == p[j+1]) j ++ ;
		if(j == m)
		{
			f = i - m;
			break;
		}
	}
	printf("\n");
	printf("%d\n",f);
	return 0;
}

7-13 图深度优先遍历 (10 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef unsigned long long ULL;
vector<int>v[N];
vector<int>ans;
bool st[N];
void dfs(int p){
    ans.push_back(p);
    for(auto &x : v[p]){
        if(st[x]) continue;
        st[x] = true;
        dfs(x);
    }
}

int main()
{
    int n,m;
    cin >> n >> m;
    for(int i = 0;i < m;i ++){
        int a,b;
        cin >> a >> b;
        v[a].push_back(b);
    }
    
    for(int i = 0;i < n;i ++){
        sort(v[i].begin(),v[i].end());
    }
    for(int i = 0;i < n;i ++){
        if(st[i]) continue;
        st[i] = true;
        dfs(i);
    }
    // dfs(0);
    for(auto &x : ans){
        cout << x << ' ';
    }
        
    return 0;
}

7-14 图的先深搜索 (15 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef unsigned long long ULL;

int h[N],e[N],ne[N],idx;
void add(int a,int b){
    e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
}
bool st[N];
vector<int>ans;

void dfs(int p,int fa)
{
    ans.push_back(p);
    
    for(int i = h[p];~i;i = ne[i]){
        int j = e[i];
        if(st[j] || j == fa) continue;
        st[j] = true;
        dfs(j,p);
    }
    
}

int main()
{
    memset(h,-1,sizeof h);
    int n,m,s;
    cin >> n >> m >> s;
    
    for(int i = 0;i < m;i ++){
        int a,b;
        cin >> a >> b;
        add(a,b);
        add(b,a);
    }
    st[s] = true;

    dfs(s,0);
    
    for(auto &x: ans){
        cout << x << ' ';
    }
    cout << endl;
    if(ans.size() != n) cout << 0 << endl;
        
    return 0;
}

7-15 迷宫-广度策略 (80 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1100;
typedef pair<int,int> PII;
int g[N][N];
int dx[] = {0,1,1,1,0,-1,-1,-1};
int dy[] = {1,1,0,-1,-1,-1,0,1};
int fx,fy,sx,sy;
int n;

PII pre[N][N];
bool st[N][N];
void bfs()
{
    queue<PII> q;
    q.push({sx,sy});
    pre[sx][sy] = {-1,-1};
    while(q.size()){
        
        auto t = q.front();
        q.pop();
        int x = t.first,y = t.second;
        for(int i = 0;i < 8;i ++){
            int a = x + dx[i],b = y + dy[i];
            if(a < 0 || a >= n || b < 0 || b >= n) continue;
            if(g[a][b] || st[a][b]) continue;
            st[a][b] = true;
            pre[a][b] = t;
            if(t.first == fx && t.second == fy) return;
            q.push({a,b});
        }
    }
}
void dfs(int x,int y)
{
    cout << x << ' ' << y << ';';
    if(x == sx && y == sy) return;
    dfs(pre[x][y].first,pre[x][y].second);
}
int main()
{
    cin >> n;
    for(int i = 0;i < n;i ++)
        for(int j = 0;j < n;j ++)
            cin >> g[i][j];
    cin >> sx >> sy >> fx >> fy;
    bfs();
    dfs(fx,fy);
    return 0;
}

7-16 图的先广搜索 (15 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef unsigned long long ULL;

int h[N],e[N],ne[N],idx;
void add(int a,int b){
    e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
}
bool st[N];
vector<int>ans;

void bfs(int p)
{
    queue<int>q;
    q.push(p);
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        ans.push_back(t);
        for(int i = h[t];~i;i = ne[i]){
            int j = e[i];
            if(st[j]) continue;
            st[j] = true;
            q.push(j);
        }
    }
}

int main()
{
    memset(h,-1,sizeof h);
    int n,m,s;
    cin >> n >> m >> s;
    
    for(int i = 0;i < m;i ++){
        int a,b;
        cin >> a >> b;
        add(a,b);
        add(b,a);
    }
    
    st[s] = true;
    bfs(s);
    
    for(auto &x: ans){
        cout << x << ' ';
    }
    cout << endl;
    if(ans.size() != n) cout << 0 << endl;
        
    return 0;
}

7-17 插入排序还是归并排序 (25 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1100;
int n;
int a[N];
int c[N];
int b[N];

bool check(int a[],int b[]){
    
    for(int i = 1;i <= n;i ++){
        if(a[i] != b[i]) return false;
    }
    return true;
}

void insertsort()
{
    bool flag = false;
    
    for(int i = 2;i <= n;i ++){
        sort(a + 1,a + 1 + i);
        if(flag){
            cout << "Insertion Sort" << endl;
            for(int i = 1;i <= n;i ++){
                if(i == n) cout << a[i];
                else
                    cout << a[i] << ' ';
            }
            return;
        }
        if(check(a,b)){
             flag = true;
        }
    }   
}

void mergesort()
{
    bool flag = false;
    
    for(int i = 2;;i *= 2){
        for(int j = 0;j < n;j += i){
            int r = j + i;
            if(r > n) r = n;
            sort(c + 1 + j,c + 1 + r);    
            
        }
        if(flag){
            cout << "Merge Sort" << endl;
            for(int i = 1;i <= n;i ++){
                if(i == n) cout << c[i];
                else
                    cout << c[i] << ' ';
            }
            return;
        }
        if(check(c,b)){
             flag = true;
        }
        
        if(i > n) return;
    }
}


int main()
{
    cin >> n;
    for(int i = 1;i <= n;i ++)
    {
        cin >> a[i];
        c[i] = a[i];
    }
    for(int i = 1;i <= n;i ++)
        cin >> b[i];
    
    insertsort();
    mergesort();
    
    return 0;
}

7-18 插入排序还是堆排序 (25 分)

  • 百度
#include <iostream>

using namespace std;

const int N = 110;

int n;
int a[N], b[N];

void down(int u, int size)
{
    int t = u;
    if (u * 2 <= size && b[t]<b[u * 2]) t = u * 2;
    if (u * 2 + 1 <= size && b[t]<b[u * 2 + 1]) t = u * 2 + 1;
    if (t != u)
    {
        swap(b[t], b[u]);
        down(t, size);
    }
}
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) cin >> b[i];

    int p = 2;
    while (p <= n && b[p] >= b[p - 1]) p++;
    int k = p;
    while (p <= n && a[p] == b[p]) p++;
    if (p == n + 1)//说明是插入排序 
    {
        cout << "Insertion Sort" << endl;
        while (k>1 && b[k]<b[k - 1]) swap(b[k], b[k - 1]), k--;
    }
    else //否则说明一定是堆排序 
    {
        cout << "Heap Sort" << endl;
        p = n;
        while (b[1] <= b[p]) p--;
        swap(b[1], b[p]);
        down(1, p - 1);
    }

    cout << b[1];
    for (int i = 2; i <= n; i++) cout << ' ' << b[i];
    cout << endl;

    return 0;
}

7-19 判断一个有向图是否能够完成拓扑排序 (90 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;

int h[N],e[N],ne[N],idx;
void add(int a,int b){
    e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
}
bool st[N];
int din[N];
int n;
bool topsort()
{
    queue<int>q;
    
    for(int i = 0;i <= n;i ++){
        if(!din[i]) q.push(i);
    }
    int cnt = 0;
    
    while(q.size()){
        auto t = q.front();
        cnt ++;
        q.pop();
        for(int i = h[t];~i;i = ne[i]){
            int j = e[i];
            din[j] --;
            if(din[j] == 0){
                q.push(j);   
            }
        }
    }
    return cnt == n + 1;
}

int main()
{
    memset(h,-1,sizeof h);
    int a,b;
    while(cin >> a >> b){
        if(a == -1 && b == -1) break;
        add(a,b);
        din[b] ++;
        n = max({a,b,n});
    }
    
    cout << topsort() << endl;
    return 0;
}

7-20 全排列 (30 分)

  • 康托展开,逆康托展开
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
typedef long long LL;
LL fact(LL x)
{
    LL res = 1;
    for (LL i = 2; i <= x; ++ i) res *= i;
    return res;
}
string uncantor(int n, LL inx) // 求在长度为n的序列中,从小到达排列,排第inx的序列是多少(从1开始)
{
    string res;
    int vis[n * n];
    memset(vis, 0, sizeof vis);

    -- inx; // 比当前序列小的序列有inx个

    for (int i = (n - 1); ~i; -- i)
    {
        LL c = inx / fact(i), s = inx % fact(i);

        LL cnt = 0, num;
        for (LL j = 1; j <= n; ++ j)
        {
            if (!vis[j])  ++ cnt;
            if (cnt == c + 1) // 找到第c+1小的数
            {
                num = j;
                break; 
            }
        }
        vis[num] = 1;
        res += to_string(num);
        res += ' ';
        inx = s;
    }
    res.pop_back();
    return res;
}
int main()
{
    LL t;
    cin >> t;
    while(t --){
        LL n,m;
        cin >> n >> m;
       cout << uncantor(n, m) << endl;
    }
    return 0;
}

  • 7-21
// 我自己写的代码,不优美但是应该没啥问题
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{   
    
    int n;
    cin >> n;
    string str;
    for(int i = 1;i <= n;i ++){
        str += i + '0';
    }
    
    do
    {
        cout << str << endl;
    } while (next_permutation(str.begin(), str.end()));

}
  • 7-22
// 我自己写的代码,不优美但是应该没啥问题
#include <bits/stdc++.h>
using namespace std;


int main()
{   
    int n,m;
    set<int>s1,s2;
    cin >> n >> m;
    for(int i = 0;i < n;i ++){
        int x;
        cin >> x;
        s1.insert(x);
    }
    
    for(int i = 0;i < m;i ++){
        int x;
        cin >> x;
        if(s1.count(x)){
            s2.insert(x);
        }
    }
    
    cout << s2.size() << endl;
    
    bool flag = false;
    for(auto &x : s2){
        
        if(flag) cout << ' ';
        flag = true;
        cout << x;
    }
    
    
    return 0;
}
  • 7-23
#include <iostream>
using namespace std;
#include <vector>
struct Node{
 
	int data;
	Node*next;
};
 
int main()
{
	int n, m;
	cin >> n >> m;
 
	vector<int>res;
	Node * first = new Node;
	//first->next =nullptr;
	Node *pre = new Node;
	Node * p = new Node;
 
	pre = first;
	pre->next = p;
	p = first;
	if (n){
		pre->data = 1;
	}
	for (int i = 2; i <= n; i++)
	{
		Node * pc = new Node;
		pc->data = i;
		pc->next = nullptr;
		p->next = pc;
		p = pc;
	}
 
	p->next = pre;
 
	//cout << "pre->data = " << pre->data <<"p->next = "<<p->data<< endl;
 
	int cnt = 1;
	for (auto i = pre,j = p;n; i = i->next)
	{
 
 
		if (cnt == m)
		{
			auto pr = i;
			res.push_back(i->data);
			//cout << i->data << " ";
			j->next = i->next;
		//delete pr;
			n--;
			cnt = 0;
		}
		cnt++;
		j = i;
		//system("pause");
	}
 
	bool tf = false;
	for (auto &x : res)
	{
		if (tf)
			cout << " ";
		cout << x;
		tf = true;
	}
 
	system("pause");
	return 0;
}
  • 7-24 二分查找 (20 分)
#include <bits/stdc++.h>
using namespace std;

const int N = 1100;
int a[N];
int main()
{   
    int n;
    cin >> n;
    
    for(int i =0;i < n;i ++){
        cin >> a[i];
    }
    int x;
    cin >> x;
    
    int l = 0,r = n - 1;
    int cnt = 0;
    while(l < r){
        
        int mid = l + r + 1 >> 1;
        cnt ++;
        if(a[mid] > x){
            r = mid - 1;
        }else{
            l = mid;
        }
    }
    if(a[l] != x) l = -1;
    cout << l << endl;
    cout << cnt << endl;
    
    
    return 0;
}
  • 7-25 两个有序序列的中位数 (25 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N];
int b[N];
int c[N];
int main()
{   
    int n;
    cin >> n;
    for(int i = 0;i < n;i ++){
        cin >> a[i];
    }
    
    for(int i = 0;i < n;i ++){
        cin >> b[i];
    }
    int cnt = 0;
    int i,j;
    for(i = 0,j = 0;i < n && j < n;)
    {
        if(a[i] > b[j]){
            c[cnt ++] = b[j];
            j ++;
        }else{
            c[cnt ++] = a[i];
            i ++;
        }
    }
    
    for(int k = i;k < n;k ++){
        c[cnt ++] = a[k];
    }
    
    for(int k = j;k < n;k ++){
        c[cnt ++] = b[k];
    }
    
  /*  for(int i = 0;i < cnt;i ++){
        cout << c[i] << ' ';
    }*/
    
    cout << c[(n * 2 - 1) >> 1] << endl;
    
    
    return 0;
}
  • 7-26
#include <bits/stdc++.h>
using namespace std;
const int N = 11;

pair<char,char>tree[N];
int din[N];
vector<int> vec;

void bfs(int p)
{
    queue<int>q;q.push(p);
    
    while(q.size())
    {
        p = q.front();q.pop();
        if(tree[p].first == '-' && tree[p].second == '-'){
            vec.push_back(p);
        }
        
        if(tree[p].first != '-'){
            int t = tree[p].first - '0';
            q.push(t);
        }
        
        if(tree[p].second != '-'){
            int t = tree[p].second - '0';
            q.push(t);
        }
        
    }
    
    
}

int main()
{   
    int n;
    cin >> n;
    
    for(int i = 0;i < n;i ++)
    {
        char l,r;
        cin >> l >> r;
        tree[i].first = l;
        tree[i].second = r;
        if(l != '-'){
            int t = l - '0';
            din[t] ++;
        }
        if(r != '-'){
            int t = r - '0';
            din[t] ++;
        }
    }
    int root = 0;
    for(int i = 0;i < n;i ++){
        if(din[i] == 0) root = i;
    }
    
    bfs(root);
    for(int i = 0;i < vec.size();i ++){
        if(i == vec.size() - 1){
            cout << vec[i] << endl;
        }else{
            cout << vec[i] << ' ';
        }
    }
    
    return 0;
}
  • 7-27
#include<stdio.h>
#include<stdlib.h>
struct tree
{
    struct tree* leftchild;
    int data;
    struct tree* rightbrother;
};
int answer;
struct tree* front;
struct tree* rear;
int path[100];
void create(struct tree* p)            //创建树
{
    struct tree* left,*right;
    int a;
    scanf("%d",&a);
    if(a==0)
    {
        p->data=0;
        return;
    }
    else
    {
        left=(struct tree*)malloc(sizeof(struct tree));
        right=(struct tree*)malloc(sizeof(struct tree));
        p->data=a;
        p->leftchild=left;
        p->rightbrother=right;
        create(p->leftchild);
        create(p->rightbrother);
    }
};

int maxnum(int a,int b,int c)                       //比较最大值
{
    if(a>=b&&a>=c)
        return a;
    if(b>a&&b>c)
    return b;
    if(c>b&&c>a)
    return c;
}

int minnum(int a,int b,int c)                           //比较最小值
{
    if(a<=b&&a<=c)
    return a;
    if(b<a&&b<c)
    return b;
    if(c<b&&c<a)
    return c;
}

void dpxian(struct tree* p,int max,int min)             //在先根遍历中更新状态
{
    int a=max;
    int b=min;
    max=maxnum(p->data*a,p->data*b,p->data);        //状态转移,由于负数的存在,需要一个最大一个最小
    min=minnum(p->data*a,p->data*b,p->data);
    if(answer<max)
    {
        if(max==p->data)
        front=p;
        answer=max;
        rear=p;
    } 
    if(p->leftchild->data!=0)
    dpxian(p->leftchild,max,min);
    while(p->rightbrother->data!=0)
    {
        dpxian(p->rightbrother,a,b);//使用上一层的最大和最小值
        p=p->rightbrother;
    }
}
void print(struct tree* p,int path[],int dep)
{
    if(p->data==0)
    return;
    path[dep]=p->data;
    if(p==rear)
    {
        int i;
        for(i=0;i<=dep;i++)
        printf("%d ",path[i]);
        exit;
    }
    print(p->leftchild,path,dep+1);
    print(p->rightbrother,path,dep);
}
int main(void)
{
    struct tree* head;
    int dep=0;
    int path[100];
    int i,a[100]={0};         //树的深度初始化时要从0开始
    head=(struct tree*)malloc(sizeof(struct tree));
    create(head);
    int max=1,min=1;//动态规划状态
    dpxian(head,max,min);
    printf("%d\n",answer);
    print(front,path,dep);
    return 0;
}

  • 7-28
#include <bits/stdc++.h>
using namespace std;

const int N = 2e6 + 10;
int a[N];

int main()
{
    ios::sync_with_stdio(false);
    int n,k;
    cin >> n >> k;
    
    for(int i = 0;i < n;i ++)
        cin >> a[i];
    sort(a,a+n);
    cout << a[n-k] << endl;
    
    return 0;
}
  • 7-29
3    3    4    4    8    8    9    9    
3    2    0    4    8    7    7    9    
5    2    2    6    10   10   7    11   
5    5    6    6    1    10   11   11   
13   13   14   1    1    18   19   19   
13   12   14   14   18   18   17   19   
15   12   12   16   20   17   17   21   
15   15   16   16   20   20   21   21   
  • 7-30
1 2 3 4 5 6 7 8 
2 1 4 3 6 5 8 7 
3 4 1 2 7 8 5 6 
4 3 2 1 8 7 6 5 
5 6 7 8 1 2 3 4 
6 5 8 7 2 1 4 3 
7 8 5 6 3 4 1 2 
8 7 6 5 4 3 2 1 
  • 7-31
#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;

int a[N];
int n,k;
int BinarySearch1(int x)
{
    int l = 0,r = n - 1;
    while(l < r){
        int mid = l + r >> 1;
        if(a[mid] < x){
            l = mid + 1;   
        }else{
            r = mid;
        }
    }
    return l;
}


int BinarySearch2(int x)
{
    int l = 0,r = n - 1;
    while(l < r){
        int mid = l + r + 1 >> 1;
        if(a[mid] > x){
            r = mid - 1;   
        }else{
            l = mid;
        }
    }
    return l;
}
int main()
{

    cin >> n >> k;
    for(int i = 0;i < n;i ++) cin >> a[i];
    if(k < a[0]){
        cout << "-1 0" << endl;
    }else if(k > a[n - 1]){
        cout << n - 1 << ' ' << n << endl;
    }else{
        int l1 = BinarySearch1(k);
        int l2 = BinarySearch2(k);
        cout << l2 << ' ' << l1 << endl;
    }
    
    return 0;
}
  • 7-32
#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;

int a[N];
int n,k;
typedef long long LL;
int main()
{
    cin >> n;
    for(int i = 0,x;i < n;i ++)
        cin >> x >> a[i];
    sort(a,a+n);
    
    int mid = a[n >> 1];
    LL sum = 0;
    for(int i = 0;i < n;i ++){
        sum += fabs(a[i] - mid);
    }
    cout << sum << endl;

    return 0;
}

/*
1,3,8
4-1+4-3+8-4



*/
  • 7-33
#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;

int a[N];
int n,k;
int BinarySearch1(int x)
{
    int l = 0,r = n - 1;
    while(l < r){
        int mid = l + r >> 1;
        if(a[mid] < x){
            l = mid + 1;   
        }else{
            r = mid;
        }
    }
    return l;
}


int BinarySearch2(int x)
{
    int l = 0,r = n - 1;
    while(l < r){
        int mid = l + r + 1 >> 1;
        if(a[mid] > x){
            r = mid - 1;   
        }else{
            l = mid;
        }
    }
    return l;
}
int main()
{
    ios::sync_with_stdio(false);
    
    cin >> n >> k;
    for(int i = 0;i < n;i ++) cin >> a[i];
    if(k < a[0]){
        cout << a[0] << endl;
    }else if(k > a[n - 1]){
        cout << a[n - 1] << endl;
    }else{
        int l1 = BinarySearch1(k);
        int l2 = BinarySearch2(k);
        int f1 = k - a[l2],f2 = a[l1] - k;
        if(f1 <= f2){
            cout << a[l2] << endl;
        }else{
            cout << a[l1] << endl;
        }
    }
    
    return 0;
}
  • 7-34
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 30;

int l[N], r[N], v[N], h[N], idx;

void update(int u)
{
    h[u] = max(h[l[u]], h[r[u]]) + 1;
}

void R(int& u)
{
    int p = l[u];
    l[u] = r[p], r[p] = u;
    update(u), update(p);
    u = p;
}

void L(int& u)
{
    int p = r[u];
    r[u] = l[p], l[p] = u;
    update(u), update(p);
    u = p;
}

int get_balance(int u)
{
    return h[l[u]] - h[r[u]];
}

void insert(int& u, int w)
{
    if (!u) u = ++ idx, v[u] = w;
    else if (w < v[u])
    {
        insert(l[u], w);
        if (get_balance(u) == 2)
        {
            if (get_balance(l[u]) == 1) R(u);
            else L(l[u]), R(u);
        }
    }
    else
    {
        insert(r[u], w);
        if (get_balance(u) == -2)
        {
            if (get_balance(r[u]) == -1) L(u);
            else R(r[u]), L(u);
        }
    }

    update(u);
}

int main()
{
    int n, root = 0;
    cin >> n;

    while (n -- )
    {
        int w;
        cin >> w;
        insert(root, w);
    }

    cout << v[root] << endl;

    return 0;
}
  • 7-35
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>

using namespace std;

void PrintHeap(vector<int>& Minimum_heap);
int main()
{
    int n, k, m;
    scanf("%d%d", &n, &k);//n是堆的容量,需创建一个容量为n的堆。
    //接下来k行,是对这个堆的依次的k项插入或删除操作:用 1 x 表示插入元素x;
    //用 -1 表示删除堆顶。
    vector<int> minHeap_1, minHeap_2;
    make_heap(minHeap_1.begin(), minHeap_1.end(), greater<int>());
    int operate_number, insert_number, i;
    for(i = 0; i < k; i++)
    {
        scanf("%d", &operate_number);
        if(operate_number == 1)
        {
            scanf("%d", &insert_number);
            if((int)minHeap_1.size() < n)//堆满则不能插入元素
            {
                minHeap_1.push_back(insert_number);
                push_heap(minHeap_1.begin(), minHeap_1.end(), greater<int>());
            }
            PrintHeap(minHeap_1);
        }
        else if(operate_number == -1)
        {
            if(!minHeap_1.empty())//堆空不可删除
            {
                pop_heap(minHeap_1.begin(), minHeap_1.end(), greater<int>());
                minHeap_1.pop_back();
            }
            PrintHeap(minHeap_1);
        }
    }
    scanf("%d", &m);
    for(int i = 0; i < m; i++)
    {
        scanf("%d", &insert_number);
        minHeap_2.push_back(insert_number);
    }
    make_heap(minHeap_2.begin(), minHeap_2.end(), greater<int>());
    //这一步尤其关键,执行了这一句后会对vector中所有的元素做调整,使之
    //成为一个最小堆
    PrintHeap(minHeap_2);
    return 0;
}
void PrintHeap(vector<int>& Minimum_heap)
{
    int heap_size = Minimum_heap.size();
    vector<int>::iterator ptr = Minimum_heap.begin();
    for (int i = 1; i < heap_size; i++, ptr++)
    {
        printf("%d ", *ptr);
    }
    printf("%d\n", *ptr);
}


  • 7-36
#include <bits/stdc++.h>
using namespace std;

const int N = 30;
int l[N],r[N],e[N],idx;
int h[N];
int n;

void update(int u)
{
    h[u] = max(h[l[u]],h[r[u]]) + 1;
}

int get_balance(int u)
{
    return h[l[u]] - h[r[u]];
}

void R(int &u)
{
    int p = l[u];
    l[u] = r[p];
    r[p] = u;
    update(u),update(p);
    u = p;
}
void L(int &u)
{
    int p = r[u];
    r[u] = l[p];
    l[p] = u;
    update(u),update(p);//更新高度。
    u = p;
}



void insert(int &u,int val)
{
    if(u == -1) e[idx] = val,u = idx ++;
    else if(val < e[u]){
        insert(l[u],val);
        if(get_balance(u) == 2){
            if(get_balance(l[u]) == 1) R(u);
            else L(l[u]),R(u);
        }
    }else{
        insert(r[u],val);
        if(get_balance(u) == -2){
            if(get_balance(r[u]) != -1) R(r[u]);
            L(u);
        }
    }
    
    update(u);
    
}

int main()
{
    memset(l,-1,sizeof(l));
    memset(r,-1,sizeof(r));
    
    int root = -1;
    cin >> n;
    int a;
    while(n --){
        cin >> a;
        insert(root,a);
    }
    
    cout << e[root] << endl;
    
    return 0;
}

7-37 Hashing (25 分)

#include <iostream>

using namespace std;

const int N = 10010;

int s, n;
int h[N];

bool is_prime(int x)
{
    if (x == 1) return false;

    for (int i = 2; i * i <= x; i ++ )
        if (x % i == 0)
            return false;

    return true;
}

int find(int x)
{
    int t = x % s;

    for (int k = 0; k < s; k ++ )
    {
        int i = (t + k * k) % s;
        if (!h[i]) return i;
    }

    return -1;
}

int main()
{
    cin >> s >> n;

    while (!is_prime(s)) s ++ ;

    for (int i = 0; i < n; i ++ )
    {
        int x;
        cin >> x;
        int t = find(x);

        if (t == -1) printf("-");
        else
        {
            h[t] = x;
            printf("%d", t);
        }

        if (i != n - 1) printf(" ");
    }

    return 0;
}

7-38 Hashing - Hard Version (30 分)

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;
const int maxn=1010;
const int inf=999999;
vector<int> indegree;
bool visit[maxn];
int e[maxn][maxn];
int a[maxn];
int count[maxn];
int n,cnt;
void topSort(){     //拓扑排序
    queue<int> q;
    for(int i=0;i<n;i++){
        int u=-1,min=inf;
        for(int j=0;j<n;j++){
            if(visit[j]==false&&!indegree[j])
                if(a[j]<min){       //每次都选取最小的入队(其实用数组输出也一样)
                    min=a[j];
                    u=j;
                }
        }
        if(u==-1) break;
        visit[u]=true;
        q.push(a[u]);
        for(int v=0;v<n;v++){
            if(visit[v]==false&&e[u][v]){
                e[u][v]=0;
                indegree[v]--;
            }
        }
    }
    int flag=0;
    while(!q.empty()){      //输出
        if(q.front()!=-1){
            if(!flag){
                cout<<q.front();
                q.pop();
                flag=1;
            }else{
                cout<<" ";
                cout<<q.front();
                q.pop();
            }
        }else{
            q.pop();
        }
    }
}
int main()
{
    fill(e[0],e[0]+maxn*maxn,0);
    cin>>n;
    cnt=n;
    indegree.resize(n);
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    for(int i=0;i<n;i++){
        if(a[i]==-1) continue;
        int index=a[i]%n;
        if(index!=i){
            indegree[i]=(i-index+n)%n;  //计算入度
            for(int j=0;j<indegree[i];j++)
                e[(index+j)%n][i]=1;   //计算连通的边
        }
    }
    topSort();
    return 0;
}

7-39 妈妈再也不用担心我被拖库啦! (25 分)

#include<iostream>
#include<string>
#include<map>
using namespace std;
struct Node{
	string c; //操作符记录
	string zh; //账号
	string mm; //密码
	string hx; //密码所对应的哈希值
};
int n;
Node node[1005];
map<string,pair<string,string> > mp;//已注册账号信息存储,map中第一个参数为账号,第二个参数为pair型,pair中第一个参数为密码,第二个参数为密码对应的哈希值。
char small_Hash(string str){ //计算字串的哈希值,返回一个字符char
	int sum=0;
	for(int i=0;i<str.length();i++){
		if(str[i]>='A'&&str[i]<='Z') str[i]=str[i]|32;
		if(str[i]>='0'&&str[i]<='9'){
			sum+=str[i]-'0';
		}else{
			sum+=str[i]-'a'+10;
		}
	}
	//cout<<"sum:"<<sum<<endl;
	sum=sum%36;
	if(sum<10) return sum+'0';
	else return sum-10+'a';
}
string Hash(string str){ //计算密码的哈希值,返回四位字符串
	string hx="0000";
	int l=str.length();
	int index[5]={0};
	for(int i=0;i<l%4;i++){
		index[i]++;
	}
	int j=0;
	for(int i=0;i<4;i++){
		index[i]+=l/4;
		string str1=str.substr(j,index[i]);
		//cout<<"str1:"<<i<<":"<<str1<<endl;
		j+=index[i];
		char h=small_Hash(str1);
		hx[i]=h;
	}
	return hx;
}
int main(void){
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>node[i].c>>node[i].zh>>node[i].mm;
		node[i].hx=Hash(node[i].mm);
		//cout<<node[i].hx<<endl;
		if(node[i].c=="R"){
			if(mp.find(node[i].zh)!=mp.end())cout<<"Repeated!"<<endl;
			else {
				mp[node[i].zh].first=node[i].mm;
				mp[node[i].zh].second=node[i].hx;
				cout<<"Signed!"<<endl;
			}
		}else if(node[i].c=="L"){
			if(mp.find(node[i].zh)==mp.end()){
				cout<<"Failed!"<<endl;
			}else{
				if(mp.find(node[i].zh)->second.first==node[i].mm) cout<<"Success!"<<endl;
				else{
					//cout<<mp.find(node[i].zh)->second.second<<"   "<<node[i].hx<<endl;
					if(mp.find(node[i].zh)->second.second==node[i].hx)cout<<"Attention!"<<endl;
					else cout<<"Failed!"<<endl;
				}
			}
		}
	}		
	return 0;
} 
//int main(void){ //检验字串哈希值计算
//	string str="sdf";
//	cout<<small_Hash(str);
//	return 0;
//}


7-40 Self-printable B+ Tree (35 分)

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct node {
	struct node* left;
	int val[3];			//for nonleaf node, val[0] is the least key among its or its des' leaves
	struct node* mid;
	struct node* right;
	bool isleaf;
	int val_num;
	int ptr_num;
} Node;
typedef struct bptree {
	struct node* root;
	struct node* leaves;
} BpTree;

#define MAXKEYN 10005
#define EMP -1

Node* stack[MAXKEYN];
Node** stackptr = stack - 1;
bool push(Node* p) {
	if (stackptr == stack + MAXKEYN)return false;
	*(++stackptr) = p;
	return true;
}
Node* pop() {
	if (stackptr == stack - 1)return NULL;
	else return *(stackptr--);
}

Node* queue[MAXKEYN];
int front = 0;
int rear = -1;
bool EmptyQueue() {
	if (front == (rear + 1) % MAXKEYN)return true;
	else return false;
}
bool enqueue(Node* p) {
	if (front == (rear + 2) % MAXKEYN)return false;
	queue[++rear] = p;
	return true;
}
Node* dequeue() {
	if (EmptyQueue())return NULL;
	else return queue[front++];
}

void Arrange3(int a, int b, int c, Node* p) {
	int t;
	if (a < b) { t = a; a = b; b = t; }
	if (a < c) { t = a; a = c; c = t; }
	if (b < c) { t = b; b = c; c = t; }
	p->val[0] = c; p->val[1] = b; p->val[2] = a;
}
void Arrange4(int a, int b, int c, int d, Node* p, Node* q) {
	int t;
	if (a < b) { t = a; a = b; b = t; }
	if (a < c) { t = a; a = c; c = t; }
	if (a < d) { t = a; a = d; d = t; }
	if (b < c) { t = b; b = c; c = t; }
	if (b < d) { t = b; b = d; d = t; }
	if (c < d) { t = c; c = d; d = t; }
	p->val[0] = d; p->val[1] = c; q->val[0] = b; q->val[1] = a;
}
void InternalArrange3(Node* a, Node* b, Node* c, Node* par) {
	Node* t;
	if (a->val[0] < b->val[0]) { t = a; a = b; b = t; }
	if (a->val[0] < c->val[0]) { t = a; a = c; c = t; }
	if (b->val[0] < c->val[0]) { t = b; b = c; c = t; }
	par->left = c; par->mid = b; par->right = a;
}
void InternalArrange4(Node* a, Node* b, Node* c, Node* d, Node* par1, Node* par2) {
	Node* t;
	if (a->val[0] < b->val[0]) { t = a; a = b; b = t; }
	if (a->val[0] < c->val[0]) { t = a; a = c; c = t; }
	if (a->val[0] < d->val[0]) { t = a; a = d; d = t; }
	if (b->val[0] < c->val[0]) { t = b; b = c; c = t; }
	if (b->val[0] < d->val[0]) { t = b; b = d; d = t; }
	if (c->val[0] < d->val[0]) { t = c; c = d; d = t; }
	par1->left = d; par1->mid = c; par2->left = b; par2->mid = a;
}

bool Insert(int x, BpTree* tree_add);
bool InternalInsert(Node* new_child, Node* cur_node, BpTree* tree_add);
Node* Search(int x, BpTree tree);

int main(void)
{
	int n;
	scanf("%d", &n);
	int key[MAXKEYN] = { 0 };
	for (int i = 0; i < n; i++) {
		scanf("%d", &key[i]);
	}

	BpTree tree;
	tree.leaves = NULL;
	tree.root = NULL;
	for (int i = 0; i < n; i++) {
		if (!Insert(key[i], &tree))
			printf("Key %d is duplicated\n", key[i]);
	}

	int cnt = 1, node_num = 0;	// level order travesal
	Node* T;
	enqueue(tree.root);
	while (!EmptyQueue()) {
		T = dequeue();

		printf("[");
		if (T->isleaf) {	// is leaf, i from 0 to val_num-1
			for (int i = 0; i < T->val_num; i++) {
				if (i == T->val_num - 1)printf("%d", T->val[i]);
				else printf("%d,", T->val[i]);
			}
		}
		else {				// is internal node, i from 1 to ptr_num-1
			for (int i = 1; i < T->ptr_num; i++) {
				if (i == T->ptr_num - 1)printf("%d", T->val[i]);
				else printf("%d,", T->val[i]);
			}
		}
		printf("]");
		node_num += T->ptr_num;	//输出一个点后 node_num加上其子节点数 目的是得到下一层的节点个数
		cnt--;

		if (cnt == 0 /* && !T->isleaf */) {	// after outputting a level, need an enter
			printf("\n");				// but there's no enter at the end
			cnt = node_num;		//输出完一层后 cnt将从node_num开始递减 以确定下一层要输出多少个节点
			node_num = 0;		//node_num归零 以准备记录下下层的节点数
		}

		if (T->ptr_num >= 1) enqueue(T->left);
		if (T->ptr_num >= 2) enqueue(T->mid);
		if (T->ptr_num == 3) enqueue(T->right);
	}

	return 0;
}

bool Insert(int x, BpTree *tree_add)
{
	// if tree is empty
	if ((*tree_add).root == NULL) {
		(*tree_add).root = (*tree_add).leaves = (Node*)malloc(sizeof(Node));
		(*tree_add).root->isleaf = true;
		(*tree_add).root->val[0] = x;
		(*tree_add).root->val[1] = (*tree_add).root->val[2] = EMP;
		(*tree_add).root->val_num = 1;
		(*tree_add).root->left = (*tree_add).root->mid = (*tree_add).root->right = NULL;
		(*tree_add).root->ptr_num = 0;
		return true;
	}

	 //if x already exists
	Node* pos = Search(x, (*tree_add));
	if (pos)  return false;

	 //insert x
	// find the node where x should be
	Node* p = (*tree_add).root;
	while (!p->isleaf) {
		if (p->ptr_num == 2) {		// cur node has 1 sepa, stored in val1
			if (x < p->val[1]) { push(p); p = p->left; }
			else { push(p); p = p->mid; }
		}
		if (p->ptr_num == 3) {		// cur node has 2 sepa, stored in val1 and val2
			if (x < p->val[1]) { push(p); p = p->left; }
			else if (x >= p->val[1] && x < p->val[2]) { push(p); p = p->mid; }
			else { push(p); p = p->right; }
		}
	}
	// now, p points to the leaf node which x belongs to

	if (p->val_num == 1) {		// no need to split
		int t = p->val[0];
		p->val[0] = t > x ? x : t;
		p->val[1] = t > x ? t : x;
		p->val[2] = EMP;
		p->val_num++;
	}
	else if (p->val_num == 2) {	// no need to split
		Arrange3(p->val[0], p->val[1], x, p);
		p->val_num++;
	}
	else {						// need to split
		Node* q = (Node*)malloc(sizeof(Node));
		q->isleaf = true;
		q->left = q->mid = q->right = NULL;
		q->ptr_num = 0;
		q->right = p->right; p->right = q;	// insert q into the linked list of leaves 

		Arrange4(p->val[0], p->val[1], p->val[2], x, p, q);
		p->val_num = q->val_num = 2;

		Node* parent = pop();
		if (parent == NULL) {
			Node* newroot = (Node*)malloc(sizeof(Node));
			newroot->isleaf = false;
			newroot->val[0] = p->val[0];
			newroot->val[1] = q->val[0];
			newroot->val[2] = EMP;
			newroot->val_num = 2;
			newroot->left = p;
			newroot->mid = q;
			newroot->right = NULL;
			newroot->ptr_num = 2;

			(*tree_add).root = newroot;
		}
		else {
			InternalInsert(q, parent, tree_add);
		}
	}

	// update the vals of x's ancestors
	Node* ances;
	while (ances = pop()) {
		if (ances->ptr_num >= 1) ances->val[0] = ances->left->val[0];
		if (ances->ptr_num >= 2) ances->val[1] = ances->mid->val[0];
		if (ances->ptr_num == 3) ances->val[2] = ances->right->val[0];
	}

	return true;
}

// new_node is generated by cur_node splitting
bool InternalInsert(Node* new_child, Node* cur_node, BpTree *tree_add)
{

	if (cur_node->ptr_num == 1) {			// impossible to have just 1 ptr
	}
	else if (cur_node->ptr_num == 2) {	// no need to split
		InternalArrange3(cur_node->left, cur_node->mid, new_child,
			cur_node);
		cur_node->ptr_num++;
		// update the sepa
		cur_node->val[0] = cur_node->left->val[0];
		cur_node->val[1] = cur_node->mid->val[0];
		cur_node->val[2] = cur_node->right->val[0];
	}
	else {								// need to split
		Node* new_node = (Node*)malloc(sizeof(Node));
		new_node->isleaf = false;
		new_node->left = new_node->mid = new_node->right = NULL;
		new_node->ptr_num = 0;

		InternalArrange4(cur_node->left, cur_node->mid, cur_node->right, new_child,
			cur_node, new_node);
		cur_node->ptr_num = new_node->ptr_num = 2;
		// update the sepa
		cur_node->val[0] = cur_node->left->val[0];
		cur_node->val[1] = cur_node->mid->val[0];
		cur_node->val[2] = EMP;
		new_node->val[0] = new_node->left->val[0];
		new_node->val[1] = new_node->mid->val[0];
		new_node->val[2] = EMP;

		Node* parent = pop();
		if (parent == NULL) {	// recursion end (cur_node is root)
			Node* newroot = (Node*)malloc(sizeof(Node));
			newroot->isleaf = false;
			newroot->val[0] = cur_node->val[0];
			newroot->val[1] = new_node->val[0];
			newroot->val[2] = EMP;
			newroot->val_num = 2;
			newroot->left = cur_node;
			newroot->mid = new_node;
			newroot->right = NULL;
			newroot->ptr_num = 2;

			(*tree_add).root = newroot;
		}
		else {
			InternalInsert(new_node, parent, tree_add);
		}
	}

	return true;
}


Node* Search(int x, BpTree tree)
{
	Node* p = tree.leaves;
	while (p) {		
		if (p->val_num >= 1) {
			if (p->val[0] == x)return p;
		}
		if (p->val_num >= 2) {
			if (p->val[1] == x)return p;
		}
		if (p->val_num == 3) {
			if (p->val[2] == x)return p;
		}
		p = p->right;
	}
	return NULL;
}


7-41 凑零钱 (30 分)

#include <bits/stdc++.h>
using namespace std;
int n,m;
const int N = 1e4 + 10;
int a[N];

bool flag;
vector<int>ans;
void dfs(int sum,int u)
{
    if(flag)return;
    
    if(u == n + 1){
        return;
    }
    if(a[u] + sum > m){
        return;
    }
    else if(a[u] + sum == m){
        ans.push_back(a[u]);
        for(int i = 0;i < ans.size();i ++){
            if(i) cout << ' ';
            cout << ans[i];
        }
        flag = true;
        return;
    }else{
        ans.push_back(a[u]);
        dfs(a[u] + sum,u + 1);    
        ans.pop_back();
        dfs(sum,u + 1);
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m;
    int sum = 0;
    for(int i = 1;i <= n;i ++)
    {
         cin >> a[i];
         sum += a[i];
    }   
    if(sum < m){
        cout << "No Solution" << endl;
        return 0;
    }
    
    sort(a + 1,a + n + 1);
    while(a[n] > m){
        n --;
    }
    
    dfs(0,1);
    
    if(!flag){
        cout << "No Solution" << endl;
    }
    
    return 0;
}

7-42 矩阵链相乘问题 (20 分)

#include <bits/stdc++.h>
using namespace std;
const int MAX = 1005;
int p[MAX];
int m[MAX][MAX];
int n;
void  matrix()
{
    int i,j,r,k;
    memset(m,0,sizeof(m));
    for(r = 2; r<=n; r++)
    {
        for(i = 1; i<=n-r+1; i++)
        {
            j = i+r-1;
            m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];
            for(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])
                {
                    m[i][j] = t;
                }
            }
        }
    }
}
int main()
{
    cin>>n;
    for(int i=0; i<n+1; i++)
        cin>>p[i];
    matrix();
    cout<<m[1][n]<<endl;
    return 0;
}



7-43 真实的背包故事 (17 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 110,M = 2100;

int dp[N][M][2];
int w[N],v[N];
int main()
{
    int n,m;
    
    cin >> n >> m;
    for(int i = 1;i <= n;i ++)
        cin >> w[i] >> v[i];
    
    for(int i = 1;i <= n;i ++){
        for(int j = 0;j <= m;j ++){
            dp[i][j][0] = dp[i - 1][j][0];
            dp[i][j][1] = dp[i - 1][j][1];
            if(j >= v[i]){
                if(dp[i - 1][j - v[i]][0] + w[i] > dp[i - 1][j][0]){
                    dp[i][j][0] = dp[i - 1][j - v[i]][0] + w[i];
                    dp[i][j][1] = dp[i - 1][j - v[i]][1] + 1;
                }else if(dp[i - 1][j - v[i]][0] + w[i] == dp[i - 1][j][0]){
                    dp[i][j][1] = min(dp[i - 1][j - v[i]][1] + 1,dp[i][j][1]);
                }
            }
        }
    }
    
    cout << dp[n][m][0] << ' ' << dp[n][m][1] << endl;
    
    
    
    return 0;
}

7-44 流水作业调度 (10 分)

#include <bits/stdc++.h>
using namespace std;
const int N = 110,M = 2100;

pair<int,int>p[N];
typedef pair<int,int> PII;

int main()
{
    int n;
    
    cin >> n;
    int s1 = 0,s2 = 0;
    vector<PII>v1,v2;
    
    /*
        1.分组
        2.把first < second 的放入到v1,否则放入v2
    */
    
    for(int i = 1;i <= n;i ++)
    {
        cin >> p[i].first >> p[i].second;
        if(p[i].first < p[i].second){
            v1.push_back({p[i].first,p[i].second});
        }else{
            v2.push_back({p[i].first,p[i].second});
        }
    }
    // v1 随便排序
    sort(v1.begin(),v1.end(),[](PII p1,PII p2){
        return p1.first < p2.first;
    });
    
    // v2 中按照升序排序
    sort(v1.begin(),v1.end(),[](PII p1,PII p2){
        return p1.second < p2.second;
    });
    
    vector<PII>vec;
    for(auto &x : v1){
        vec.push_back(x);
    }
    
    for(auto &x : v2){
        vec.push_back(x);
    }
    
    s1 += vec[0].first;
    s2 += vec[0].first + vec[0].second;
    
    for(int i = 1;i < vec.size();i ++){
        s1 += vec[i].first;
        if(s1 > s2){
            s2 = s1 + vec[i].second;
        }else{
            s2 = s2 + vec[i].second;    
        }
        
    }
    
    cout << s1 << ' ' << s2 << endl;
    
    return 0;
}

7-45 月饼 (25 分)

/*
注意k的精度!!!!!!!!!!!
注意k的精度!!!!!!!!!!!
注意k的精度!!!!!!!!!!!
注意k的精度!!!!!!!!!!!
注意k的精度!!!!!!!!!!!

*/
#include <iostream>
#include <cstring>
#include <unordered_map>
#include <algorithm>
using namespace std;

const int N = 1e4+10;

struct Moon{
    
    double weight;
    double sale;
    double ave;
    
}moon[N];

int n;
double k;
int main()
{
    cin >> n >> k;
    
    for(int i = 0;i < n;i++)
    {
        cin >> moon[i].weight ;
        
    }
    
    for(int i = 0;i < n;i++)
    {
        cin >> moon[i].sale;
        moon[i].ave = moon[i].sale * 1.0 / moon[i].weight;
    }
    
    sort(moon,moon+n,[](Moon m1,Moon m2){
        return m1.ave > m2.ave;
    });
    
    double sum = 0;
    
    for(int i = 0;i < n;i++)
    {
        if(moon[i].weight < k)
        {
            k -= moon[i].weight;
            sum += moon[i].sale;
        }
        else
        {
            sum += k * 1.0 * moon[i].ave;
            break;
        }
    }
    printf("%.2lf\n",sum);
    
	return 0;
}

7-46 加油站之最小加油次数 (15 分)

#include <bits/stdc++.h>
using namespace std;

typedef pair<int,int> PII;
int main()
{
    int n;
    int s,h;
    cin >> n;
    vector<PII>vec;
    
    for(int i = 0;i < n;i ++){
        int a,b;
        cin >> a >> b;
        vec.push_back({a,b});
    }
    
    cin >> s >> h;
    
    
    sort(vec.begin(),vec.end(),[](PII p1,PII p2){
        return p1.first > p2.first;
    });
    
    priority_queue<int>heap;
    int cnt = 0;
    
    for(int i = 0;i < n;i ++){
        while(vec[i].first < s - h){
            if(heap.size() == 0){
                cout << -1 << endl;
                return 0;
            }
            h += heap.top();
            heap.pop();
            cnt ++;
        }
        h = h - (s - vec[i].first);
        s = vec[i].first;
        heap.push(vec[i].second);
    }
    
    cout << cnt << endl;
    
    
    
    return 0;
}

7-47 活动选择问题 (25 分)

#include<iostream>
#include<algorithm>
#define MAXN 1000
using namespace std;
struct Goods {
	int s;
	int e;
}goods[MAXN];
bool comp(Goods a, Goods b)
{
	return a.e <= b.e;
}
void input(int n)
{
	int i;
	for (i = 0; i <n; i++)
		cin >> goods[i].s >> goods[i].e; //输入活动开始和结束的时间
}
void select(int n)
{
	int sum = -1;
	int count = 0;
	for (int i = 0; i < n; i++)
	{
		if (goods[i].s >= sum)  
		{
			count++; 
			sum = goods[i].e;
		}

	}
	 cout << count << endl;//能安排的活动个数
}

int main()
{
	int n;//活动的总数
	while (cin >> n)
	{
		if (n == 0)break;
		input(n);
		sort(goods, goods+n, comp);//按活动结束时间从小到大排序
		select(n);
	}
	return 0;
}


7-48 最小生成树-kruskal (10 分)

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

using namespace std;

const int N = 1e6 + 10;
int n, m, p[N];

void init(){
    for (int i = 1; i <= n; i++){
        p[i] = i;
    }
}

struct Edge{
    int x, y, w;
    
    bool operator < (const Edge &W)const
    {
       return  w < W.w;
    }
}edges[N];

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

int kruskal(){
    sort(edges,edges + m);
    int res = 0;
    int cnt = 0;
    init();    
    for (int i = 0; i < m; i++){
        int x = edges[i].x, y = edges[i].y, w = edges[i].w;
        if (Find(x) != Find(y)){
            p[Find(x)] = Find(y);
            cnt ++;
            res += w;
        }
    }
    if (cnt < n - 1) return -1;
    else return res;
}

int main(){
    scanf("%d%d",&n,&m);
    
    for (int i = 0; i < m; i++){
        int a, b, c;
        scanf("%d%d%d",&edges[i].x,&edges[i].y,&edges[i].w);
    }
    
    int t = kruskal();
    
    if (t == -1) puts("impossible");
    else printf("%d\n",t);
    
    return 0;
}

7-49 最小生成树-prim (10 分)

#include <cstring>
#include <iostream>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;

const int N = 1e6+10, M = 2e6+10;

int n,m;
int p[N];

struct Edge
{
    int a, b, w;

    bool operator < (const Edge &W)const
    {
        return w < W.w;
    }
}edges[M];

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

int kruskal()
{
    sort(edges, edges + m);

    for (int i = 1; i <= n; i ++ ) p[i] = i;    // 初始化并查集

    int res = 0, cnt = 0;
    for (int i = 0; i < m; i ++ )
    {
        int a = edges[i].a, b = edges[i].b, w = edges[i].w;

        a = find(a), b = find(b);
        if (a != b)
        {
            p[a] = b;
            res += w;
            cnt ++ ;
        }
    }

    return res;
}

int main()
{
    scanf("%d%d", &n, &m);

    for (int i = 0; i < m; i ++ )
    {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[i] = {a, b, w};
    }

    int t = kruskal();

    printf("%d\n", t);

    return 0;
}

7-50 最优服务次序问题 (10 分)

#include<iostream>
#include<algorithm>

using namespace std;

int main(){
	int n,a[1000];
	cin>>n; 
	int i;
	for(i=0;i<n;i++){
		cin>>a[i];
	}
	sort(a,a+n);
	int sum=0; 
	for(i=0;i<n;i++){
		sum+=a[i]*(n-i - 1);
	} 
// 	cout<<sum/(n*1.0)<<endl;
    printf("%.2lf\n",sum*1.0/n);
	return 0;
}



7-51 删数问题 (10 分)

#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <string>
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
    char a[105];
    int n;
    while(cin >> a >> n)
    {
        int m=strlen(a);
        while(n--)
        {
            int i=0;
            while(i<m-1&&a[i]<=a[i+1])
            {
                i++;
            }
            if(i==m-1)
            {
                m--;
                while(n--)
                   m--;
                break;
            }
            else
            {
                for(int j=i;j<m-1;j++)
                    a[j]=a[j+1];
                m--;
            }
        }
        for(int i=0;i<m;i++)
          printf("%c",a[i]);
        cout << endl;
    }
    return 0;
}
// https://blog.csdn.net/lvshubao1314/article/details/19673953

7-52 求解区间覆盖问题 (10 分)

#include <iostream>
#include <algorithm>
using namespace std;
int a[1000];
int s[1000];
int cmp(int a,int b)
{
  return a>b;
}
int main()
{
    int n,m;
    int len;
    int sum;
    while(cin>>n>>m)
    {
     for(int i=0;i<=n-1;i++)
     {
      cin>>a[i];
     }
     sort(a,a+n);
     len=a[n-1]-a[0]+1;
     for(int i=0;i<n-1;i++)//求区间的间隔距离
     {
      s[i]=a[i+1]-a[i]-1;
     }
     sort(s,s+n-1,cmp);
     sum=len;
     for(int i=0;i<m-1;i++)
     {
      sum=sum-s[i];
     }
    cout << sum << endl;
    }
    return 0;
}
// https://blog.csdn.net/baidu_30309461/article/details/48399161

7-53 哈夫曼编码 (30 分)

// HuffmanCodes.cpp : 定义控制台应用程序的入口点。
//
 
//#include <stdafx.h>
#include <vector>
#include <iostream>
#include <string.h>
 
using namespace std;
 
//Huffman树结点类
class Node {
public:
	Node() {}
	Node(char element, int weight)
		:element(element), weight(weight), left(NULL), right(NULL) {}
 
	char element;
	int weight;
	Node* left = NULL;
	Node* right = NULL;
	bool isleave = false;
};
typedef Node* HFMTree;
 
//输入测试样例结点类
class Case {
public:
	char element;
	char route[1000];
	int length;
 
	int getlength() {
		return strlen(this->route);
	}
};
 
void Read(int num, vector<HFMTree>& minHeap, vector<HFMTree>& inputlist);
void Insert(vector<HFMTree>& minHeap, HFMTree node);		//插入数据创建最小堆
HFMTree CreateHFMT(vector<HFMTree>& minHeap);			//根据最小堆创建Huffman树
HFMTree DeleteMinHeap(vector<HFMTree>& minHeap);		//从最小堆中取出最小元素,删除该结点并重新调整最小堆,最后删除该结点
int getHFMLength(HFMTree hfmtree, int depth);						//获得该树编码长度
 
void Input(vector<Case>& testcase, int num);
bool isOptimalLen(vector<Case>& testcase, vector<HFMTree>& inputlist, int weight);	//检查是否符合最优编码长度
bool isPrefixCode(vector<Case>& testcase);				//检查是否符合前缀码编码
 
 
int main()
{
	/*根据输入序列建立Huffman树,并获得最优编码长度*/
	int num;
	cin >> num;
 
	vector<HFMTree> minHeap;		//创建最小堆,用最小堆对序列进行存储
	vector<HFMTree> inputlist;		//记录输入顺序与权值大小
	HFMTree flag = new Node('-', -1);
	minHeap.push_back(flag);
	Read(num, minHeap, inputlist);
 
	HFMTree hfmtree;				//利用最小堆创建Huffman树
	hfmtree = CreateHFMT(minHeap);
	int optcodelength = getHFMLength(hfmtree, 0);	//通过序列创建的Huffman树获得最优编码长度
 
 
	/*对提交数据进行检查:1.是否符合最优编码长度,2.是否符合无歧义解码规则(前缀码编码,数据仅存在于二叉树叶节点)*/
	int count;
	cin >> count;
 
	for (int i = 0;i < count;i++) {
		vector<Case> testcase;
		Input(testcase, num);
		bool isoptimallen = isOptimalLen(testcase, inputlist, optcodelength);
		bool isprefixcode = isPrefixCode(testcase);
		if (isoptimallen && isprefixcode) {
			cout << "Yes" << endl;
		}
		else {
			cout << "No" << endl;
		}
	}
 
	system("pause");
	return 0;
}
 
void Read(int num, vector<HFMTree>& minHeap, vector<HFMTree>& inputlist) {
	char element;
	int weight;
	for (int i = 0; i < num; i++) {
		cin >> element >> weight;
		HFMTree node = new Node(element, weight);
		inputlist.push_back(node);
		Insert(minHeap, node);
	}
	//minHeap.erase(minHeap.begin());
}
 
void Insert(vector<HFMTree>& minHeap, HFMTree node) {
	int index = minHeap.size();
	minHeap.push_back(node);
 
	//每次插入后自底向上进行调整
	while ((*minHeap[index / 2]).weight > (*node).weight) {
		//此处不可单纯进行值交换,需要交换两个对象
		//(*minHeap[index]).element = (*minHeap[index / 2]).element;
		//(*minHeap[index]).weight = (*minHeap[index / 2]).weight;
		minHeap[index] = minHeap[index / 2];
		index /= 2;
	}
	minHeap[index] = node;
}
 
HFMTree CreateHFMT(vector<HFMTree>& minHeap) {
 
	HFMTree hfmtree = new Node();
	int size = minHeap.size() - 1;
	//进行size-1次合并
	for (int i = 1; i < size; i++) {
		HFMTree node = new Node();
		//每次从最小堆中取出堆顶的两个结点作为该结点的左右子结点
		node->left = DeleteMinHeap(minHeap);
		node->right = DeleteMinHeap(minHeap);
		node->weight = node->left->weight + node->right->weight;
		//将该结点作为根节点的二叉树重新加入最小堆
		Insert(minHeap, node);
	}
 
	//从最小堆中取出建好的Huffman树
	hfmtree = DeleteMinHeap(minHeap);
 
	return hfmtree;
}
 
HFMTree DeleteMinHeap(vector<HFMTree>& minHeap) {
	//检查是否堆空
	if (minHeap.size() == 1) {
		return NULL;
	}
 
	//将该堆最大元素装入新结点并返回
	HFMTree node = new Node();
	node = minHeap[1];
 
	//重新调整该堆
	int size = minHeap.size();
	int parent, child;
	//用最大堆中最后一个元素从根结点开始向上过滤下层结点
	HFMTree cmp = new Node();
	cmp = minHeap[size - 1];
 
	//从根节点开始,用parent记录根结点下标,用child记录其最小子结点下标,每次循环将parent更新为上一次循环的child
	//当parent指向底层结点时跳出循环(会有极端情况比如偏向一边的堆使得parent最终并非指向该子树底层结点,但不影响结果)
	for (parent = 1; 2 * parent < size; parent = child) {
		child = parent * 2;
		//若该子结点不是堆尾结点,令child指向左右子结点中的较小者
		if ((child != size - 1) && ((*minHeap[child]).weight > (*minHeap[child + 1]).weight)) {
			child++;
		}
		//当循环到堆尾结点值小于等于该子结点值时,可以结束(此时堆尾结点会替换parent结点而不是child结点)
		if (cmp->weight <= (*minHeap[child]).weight) {
			break;
		}
		else {
			minHeap[parent] = minHeap[child];
		}
	}
	//将尾结点与当前父结点替换
	minHeap[parent] = cmp;
 
	//删除堆尾结点
	//此处不能用minHeap.erase(minHeap.end());,因为erase会返回被删除结点的下一结点,而尾结点的下一结点超限
	minHeap.pop_back();
 
	//返回该结点
	return node;
}
 
int getHFMLength(HFMTree hfmtree, int depth) {
	//若为叶子节点,直接返回其编码长度
	if (!hfmtree->left && !hfmtree->right) {
		return hfmtree->weight * depth;
	}
	//否则其他节点一定有两个子树,返回左右子树编码长度之合,深度相应加一
	else {
		return getHFMLength(hfmtree->left, depth + 1) + getHFMLength(hfmtree->right, depth + 1);
	}
}
 
void Input(vector<Case>& testcase, int num) {
	for (int i = 0;i < num;i++) {
		Case inputcase;
		cin >> inputcase.element >> inputcase.route;
		inputcase.length = inputcase.getlength();
		testcase.push_back(inputcase);
	}
}
 
bool isOptimalLen(vector<Case>& testcase, vector<HFMTree>& inputlist, int weight) {
	int testweight = 0;
	for (int i = 0;i < testcase.size();i++) {
		testweight += (testcase[i].length * (*inputlist[i]).weight);
	}
	if (testweight == weight) {
		return true;
	}
	else {
		return false;
	}
 
}
 
bool isPrefixCode(vector<Case>& testcase) {
	bool isprefixcode = true;
	HFMTree newtree = new Node();
 
	//两种情况验证不满足前缀码要求:1.后创建的分支经过或超过已经被定义的叶子结点,2.后创建分支创建结束时未达到叶子结点
	for (int i = 0;i < testcase.size();i++) {
		HFMTree point = newtree;
		if (isprefixcode == false)break;
 
		for (int j = 0;j < testcase[i].length;j++) {
 
			if (isprefixcode == false)break;
 
			if (testcase[i].route[j] == '0') {
				//先检查左子结点是否存在,若不存在,则创建一个左子结点
				if (!point->left) {
					HFMTree newnode = new Node();
					point->left = newnode;
					point = point->left;
					//若此时为分支的最后一环,则将该结点定义为叶子结点
					if (j == testcase[i].length - 1) {
						point->isleave = true;
					}
				}
				//若左子树存在,则先将标记指针移至左子树。
				else {
					point = point->left;
					//若左子树为叶子结点,则不符合要求
					if (point->isleave) {
						isprefixcode = false;
						break;
					}
					//若此时为分支的最后一环且仍有叶子结点,则不符合要求
					if ((j == testcase[i].length - 1) && (point->left || point->right)) {
						isprefixcode = false;
						break;
					}
				}
			}
			else if (testcase[i].route[j] == '1') {
				//先检查右子结点是否存在,若不存在,则创建一个右子结点
				if (!point->right) {
					HFMTree newnode = new Node();
					point->right = newnode;
					point = point->right;
					//若此时为分支的最后一环,则将该结点定义为叶子结点
					if (j == testcase[i].length - 1) {
						point->isleave = true;
					}
				}
				//若左子树存在,则先将标记指针移至左子树。
				else {
					point = point->right;
					//若左子树为叶子结点,则不符合要求
					if (point->isleave) {
						isprefixcode = false;
						break;
					}
					//若此时为分支的最后一环且仍有叶子结点,则不符合要求
					if ((j == testcase[i].length - 1) && (point->left || point->right)) {
						isprefixcode = false;
						break;
					}
				}
			}
		}
	}
 
	return isprefixcode;
}

7-54 最短路径-Dijkstra (15 分)

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6;

typedef pair<int,int> pii;

int n,m;
int h[N],ne[N],e[N],w[N],idx;
int dist[N];
bool st[N];


void add(int a,int b,int c)
{
    e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx ++ ;
}

void dijkstra(int s)
{
    memset(dist,0x3f,sizeof dist);
    dist[s] = 0;
    priority_queue<pii,vector<pii>,greater<pii> > heap;
    heap.push({0,s});
    
    while(heap.size())
    {
        auto t = heap.top();
        heap.pop();
        
        int u = t.second;
        
        if(st[u]) continue;
        
        st[u] = true;
        
        for (int i = h[u] ; i != -1 ; i = ne[i])
        {
            int p = e[i];
            if(dist[p] > dist[u] + w[i])
            {
                dist[p] = dist[u] + w[i];
                heap.push({dist[p],p});
            }
        }
    }
    
}

int main()
{
    memset(h,-1,sizeof h);
    int op;
    cin >> n >> m >> op;
    for (int i = 0 ; i < m ; i ++ )
    {
        int x,y,z;
        cin >> x >> y >> z;
        add(x,y,z);
        if(!op){
            add(y,x,z);
        }
    }
    int s;
    cin >> s;
    dijkstra(s);
    
    for(int i = 1;i <= n;i ++){
        if(dist[i] == 0x3f3f3f3f){
            printf("%d->%d:no path\n",s,i);
        }else{
            printf("%d->%d:%d\n",s,i,dist[i]);
        }
    }
    
    
    return 0;
}

7-55 最优二叉搜索树 (10 分)

#include <bits/stdc++.h>

using namespace std;

double b[15], a[15], m[15][15], w[15][15];
int s[15][15], n, MAX = 0x3f3f3f3f, tr[1025];

void obst() {
    for (int i = 0; i <= n + 1; ++i) {
        m[i][i - 1] = 0.0;
        w[i][i - 1] = a[i - 1];
    }
    for (int l = 1; l <= n; ++l) {
        for (int i = 1; i <= n - l + 1; ++i) {
            int j = i + l - 1;
            int i1 = s[i][j - 1] > i ? s[i][j - 1] : i;
            int j1 = s[i + 1][j] > i ? s[i + 1][j] : j;
            m[i][j] = (double)MAX;
            w[i][j] = w[i][j - 1] + b[j] + a[j];
            for (int r = i1; r <= j1; ++r) {
                double t = m[i][r - 1] + m[r + 1][j] + w[i][j];
                if (t <= m[i][j]) m[i][j] = t, s[i][j] = r;
            }
        }
    }
}

void getTree(int i, int j, int root) {
    tr[root] = s[i][j];
    if (i >= j) return;
    getTree(i, s[i][j] - 1, root << 1);
    getTree(s[i][j] + 1, j, root << 1 | 1);
}
void preOrder(int root) {
    if (tr[root] == 0) {
        printf(". ");
        return;
    }
    printf("%d ", tr[root]);
    preOrder(root << 1);
    preOrder(root << 1 | 1);
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%lf", &b[i]);
    for (int i = 0; i <= n; ++i) scanf("%lf", &a[i]);
    obst();
    printf("%.2f\n", m[1][n]);
    getTree(1, n, 1);
    preOrder(1);
    return 0;
}


7-56 最长递增子序列 (30 分)

#include <bits/stdc++.h>
using namespace std;

const int N = 2510;

int a[N];
int dp[N];

int main()
{
    int n;
    cin >> n;
    
    for(int i = 1;i <= n;i ++)
        cin >> a[i];
    int ans = 0;
    for(int i = 1;i <= n;i ++){
        dp[i] = 1;
        for(int j = 1;j < i;j ++){
            if(a[i] > a[j])
            dp[i] = max(dp[j] + 1,dp[i]);
            ans = max(ans,dp[i]);
        }
    }
    
    cout << ans << endl;
    
    
    return 0;
}

7-57 最小费用流 (100 分)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=100010;

bool vis[maxn];
int n,m,s,t,x,y,z,f,dis[maxn],pre[maxn],last[maxn],flow[maxn],maxflow,mincost;
//dis最小花费;pre每个点的前驱;last每个点的所连的前一条边;flow源点到此处的流量 
struct Edge{
	int to,next,flow,dis;//flow流量 dis花费 
}edge[maxn];
int head[maxn],num_edge; 
queue <int> q;

void add_edge(int from,int to,int flow,int dis)
{
	edge[++num_edge].next=head[from];
	edge[num_edge].to=to;
	edge[num_edge].flow=flow;
	edge[num_edge].dis=dis;
	head[from]=num_edge;
}

bool spfa(int s,int t)
{
	memset(dis,0x7f,sizeof(dis));
	memset(flow,0x7f,sizeof(flow));
	memset(vis,0,sizeof(vis));
	q.push(s); vis[s]=1; dis[s]=0; pre[t]=-1;
	
	while (!q.empty())
	{
		int now=q.front();
		q.pop();
		vis[now]=0;
		for (int i=head[now]; i!=-1; i=edge[i].next)
		{
			if (edge[i].flow>0 && dis[edge[i].to]>dis[now]+edge[i].dis)//正边 
			{
				dis[edge[i].to]=dis[now]+edge[i].dis;
				pre[edge[i].to]=now;
				last[edge[i].to]=i;
				flow[edge[i].to]=min(flow[now],edge[i].flow);//
				if (!vis[edge[i].to])
				{
					vis[edge[i].to]=1;
					q.push(edge[i].to);
				}
			}
		}
	}
	return pre[t]!=-1;
}

void MCMF()
{
	while (spfa(s,t))
	{
		int now=t;
		maxflow+=flow[t];
		mincost+=flow[t]*dis[t];
		while (now!=s)
		{//从源点一直回溯到汇点 
			edge[last[now]].flow-=flow[t];//flow和dis容易搞混 
			edge[last[now]^1].flow+=flow[t];
			now=pre[now];
		}
	}
}

int main()
{
	memset(head,-1,sizeof(head)); num_edge=-1;//初始化 
	scanf("%d%d",&n,&m);
	s = 1,t = n;
	for (int i=1; i<=m; i++)
	{
		scanf("%d%d%d%d",&x,&y,&z,&f);
		add_edge(x,y,z,f); add_edge(y,x,0,-f);
		//反边的流量为0,花费是相反数 
	}
	MCMF();
	printf("%d %d",maxflow,mincost);
	return 0;
}
// https://www.luogu.com.cn/problem/solution/P3381

7-58 最大流 加强版 (200 分)

#include<bits/stdc++.h>
#define RIT register int
#define up(l,r,i) for(RIT i=l;i<=r;++i)
#define lw(l,r,i) for(RIT i=l;i>=r;--i)
#define erg(u) for(RIT i=head[u];i;i=nxt[i])
using namespace std;
const int INF =2147483647;
const int MAXN = 1200+3,MAXM =120000+3;
int n,m,s,t,mxflow,cnt;
bool inque[MAXN];
int lft[MAXN],gap[MAXN],ht[MAXN];
int ver[MAXM*2],head[MAXM*2],nxt[MAXM*2],val[MAXM*2],tot=1;
inline int qread(){
    RIT ret,c;
    while((c=getchar())> '9'||c< '0');
    ret=c-'0';
    while((c=getchar())>='0'&&c<='9')
    ret=ret*10+c-'0';
    return ret;
}
inline void add(){
    RIT u=qread(),v=qread(),k=qread();
    ver[++tot]=v,nxt[tot]=head[u],head[u]=tot,val[tot]=k;
    ver[++tot]=u,nxt[tot]=head[v],head[v]=tot,val[tot]=0;
}
inline void bfs(){
    queue<int> q;
    for(q.push(t),ht[t]=0,inque[t]=true;!q.empty();){
        RIT u=q.front(),v;inque[u]=false,q.pop();
        erg(u)if(ht[v=ver[i]]>ht[u]+1&&val[i^1]&&!inque[v])
        ht[v]=ht[u]+1,q.push(v),inque[v]=true;
    }
    up(1,n,i) if(ht[i]!=INF) gap[ht[i]]++;
}
inline void update(int u){
    ht[u]=INF;
    erg(u)if(ht[u]>1+ht[ver[i]]&&val[i])ht[u]=ht[ver[i]]+1;
}
struct cmp{
    inline bool operator () (int a,int b) const{
        return ht[a]<ht[b];}
};
inline int HIPP(){
    up(1,n,i) ht[i]=INF;bfs();
    if(ht[s]==INF) return 0;
    priority_queue<int,vector<int>,cmp> pq;
    erg(s){
        lft[ver[i]]+=val[i],swap(val[i^1],val[i]);
        if(ver[i]!=t&&ver[i]!=s&&!inque[ver[i]])
        pq.push(ver[i]),inque[ver[i]]=true;
    }
    for(ht[s]=n;!pq.empty();){
        RIT u=pq.top(),v;
        inque[u]=false,pq.pop();
        for(RIT i=head[u];i&&lft[u];i=nxt[i]){
            if(!val[i]||ht[v=ver[i]]>=ht[u]) continue;
            RIT mn=min(lft[u],val[i]);
            lft[u]-=mn,val[i]-=mn,val[i^1]+=mn,lft[v]+=mn;
            if(!inque[v]&&v!=s&&v!=t) pq.push(v),inque[v]=true;
        }
        if(!lft[u]) continue;
        if(!(--gap[ht[u]])) up(1,n,i)
        if(i!=s&&i!=t&&ht[i]>ht[u]&&ht[i]<n+1) ht[i]=n+1,cnt++;
        update(u),++gap[ht[u]],pq.push(u),inque[u]=true;
        if(cnt==n) return lft[t];
    }
    return lft[t];
}
int main(){
    n=qread(),m=qread(),s=qread(),t=qread();
    up(1,m,i) add();
    printf("%d",HIPP());
    return 0;
}
// https://www.luogu.com.cn/problem/solution/P4722

7-59 搭配飞行员 (100 分)

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 110, M = 5210, INF = 1e8;

int m, n, S, T;
int h[N], e[M], f[M], ne[M], idx;
int q[N], d[N], cur[N];

void add(int a, int b, int c)
{
    e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
    e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}

bool bfs()
{
    int hh = 0, tt = 0;
    memset(d, -1, sizeof d);
    q[0] = S, d[S] = 0, cur[S] = h[S];
    while (hh <= tt)
    {
        int t = q[hh ++ ];
        for (int i = h[t]; ~i; i = ne[i])
        {
            int ver = e[i];
            if (d[ver] == -1 && f[i])
            {
                d[ver] = d[t] + 1;
                cur[ver] = h[ver];
                if (ver == T) return true;
                q[ ++ tt] = ver;
            }
        }
    }
    return false;
}

int find(int u, int limit)
{
    if (u == T) return limit;
    int flow = 0;
    for (int i = h[u]; ~i && flow < limit; i = ne[i])
    {
        cur[u] = i;
        int ver = e[i];
        if (d[ver] == d[u] + 1 && f[i])
        {
            int t = find(ver, min(f[i], limit - flow));
            if (!t) d[ver] = -1;
            f[i] -= t, f[i ^ 1] += t, flow += t;
        }
    }
    return flow;
}

int dinic()
{
    int r = 0, flow;
    while (bfs()) while (flow = find(S, INF)) r += flow;
    return r;
}

int main()
{
    scanf("%d%d", &n, &m);
    S = 0, T = n + 1;
    memset(h, -1, sizeof h);
    for (int i = 1; i <= m; i ++ ) add(S, i, 1);
    for (int i = m + 1; i <= n; i ++ ) add(i, T, 1);

    int a, b;
    while (cin >> a >> b) add(a, b, 1);

    printf("%d\n", dinic());
    /*for (int i = 0; i < idx; i += 2)
        if (e[i] > m && e[i] <= n && !f[i])
            printf("%d %d\n", e[i ^ 1], e[i]);*/

    return 0;
}
// https://www.luogu.com.cn/problem/P2756

7-60 数字梯形 (110 分)

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1200, M = 4000, INF = 1e8;

int m, n, S, T;
int h[N], e[M], f[M], w[M], ne[M], idx;
int q[N], d[N], pre[N], incf[N];
bool st[N];
int id[40][40], cost[40][40];

void add(int a, int b, int c, int d)
{
    e[idx] = b, f[idx] = c, w[idx] = d, ne[idx] = h[a], h[a] = idx ++ ;
    e[idx] = a, f[idx] = 0, w[idx] = -d, ne[idx] = h[b], h[b] = idx ++ ;
}

bool spfa()
{
    int hh = 0, tt = 1;
    memset(d, -0x3f, sizeof d);
    memset(incf, 0, sizeof incf);
    q[0] = S, d[S] = 0, incf[S] = INF;
    while (hh != tt)
    {
        int t = q[hh ++ ];
        if (hh == N) hh = 0;
        st[t] = false;

        for (int i = h[t]; ~i; i = ne[i])
        {
            int ver = e[i];
            if (f[i] && d[ver] < d[t] + w[i])
            {
                d[ver] = d[t] + w[i];
                pre[ver] = i;
                incf[ver] = min(f[i], incf[t]);
                if (!st[ver])
                {
                    q[tt ++ ] = ver;
                    if (tt == N) tt = 0;
                    st[ver] = true;
                }
            }
        }
    }
    return incf[T] > 0;
}

int EK()
{
    int cost = 0;
    while (spfa())
    {
        int t = incf[T];
        cost += t * d[T];
        for (int i = T; i != S; i = e[pre[i] ^ 1])
        {
            f[pre[i]] -= t;
            f[pre[i] ^ 1] += t;
        }
    }
    return cost;
}

int main()
{
    int cnt = 0;
    scanf("%d%d", &m, &n);
    S = ++ cnt;
    T = ++ cnt;
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m + i - 1; j ++ )
        {
            scanf("%d", &cost[i][j]);
            id[i][j] = ++ cnt;
        }

    // 规则1
    memset(h, -1, sizeof h), idx = 0;
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m + i - 1; j ++ )
        {
            add(id[i][j] * 2, id[i][j] * 2 + 1, 1, cost[i][j]);
            if (i == 1) add(S, id[i][j] * 2, 1, 0);
            if (i == n) add(id[i][j] * 2 + 1, T, 1, 0);
            if (i < n)
            {
                add(id[i][j] * 2 + 1, id[i + 1][j] * 2, 1, 0);
                add(id[i][j] * 2 + 1, id[i + 1][j + 1] * 2, 1, 0);
            }
        }
    printf("%d\n", EK());

    // 规则2
    memset(h, -1, sizeof h), idx = 0;
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m + i - 1; j ++ )
        {
            add(id[i][j] * 2, id[i][j] * 2 + 1, INF, cost[i][j]);
            if (i == 1) add(S, id[i][j] * 2, 1, 0);
            if (i == n) add(id[i][j] * 2 + 1, T, INF, 0);
            if (i < n)
            {
                add(id[i][j] * 2 + 1, id[i + 1][j] * 2, 1, 0);
                add(id[i][j] * 2 + 1, id[i + 1][j + 1] * 2, 1, 0);
            }
        }
    printf("%d\n", EK());

    // 规则3
    memset(h, -1, sizeof h), idx = 0;
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m + i - 1; j ++ )
        {
            add(id[i][j] * 2, id[i][j] * 2 + 1, INF, cost[i][j]);
            if (i == 1) add(S, id[i][j] * 2, 1, 0);
            if (i == n) add(id[i][j] * 2 + 1, T, INF, 0);
            if (i < n)
            {
                add(id[i][j] * 2 + 1, id[i + 1][j] * 2, INF, 0);
                add(id[i][j] * 2 + 1, id[i + 1][j + 1] * 2, INF, 0);
            }
        }
    printf("%d\n", EK());

    return 0;
}

7-61 孤岛营救问题 (60 分)

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 105,M = 12;
typedef pair<int,int> PII;
int g[N][N],key[N],d[N][1<<M];
bool st[N][1<<M];
int n,m,p,k,s;
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};
queue<PII> q;
int get(int x,int y){
    return (x - 1) * m + y;
}
int bfs(){
    int t = get(1,1);
    q.push({t,key[t]});
    st[t][key[t]] = true;
    memset(d,0x3f,sizeof d);
    d[t][key[t]] = 0;
    while(q.size()){
        PII u = q.front();
        q.pop();
        int z = u.first,v = u.second;
        for(int i = 0;i < 4;i++){
            int x = (z - 1) / m + dx[i] + 1,y = (z - 1) % m + dy[i] + 1;
            int v1 = v,z1 = get(x,y);
            if(!x || !y || x > n || y > m || !g[z][z1]) continue;
            if(g[z][z1] != -1){
                if(!(v >> g[z][z1] & 1))    continue;
            }
            v1 |= key[z1];
            if(!st[z1][v1]){
                q.push({z1,v1});
                st[z1][v1] = true;
                d[z1][v1] = d[z][v] + 1;
            } 
            if(z1 == n * m) return d[z1][v1];
        }
    }
    return -1;
}
int main(){
    cin>>n>>m>>p;
    cin>>k;
    int x1,y1,x2,y2,z,z1,z2;
    memset(g,-1,sizeof g);
    while(k--){
        cin>>x1>>y1>>x2>>y2>>z;
        z1 = get(x1,y1),z2 = get(x2,y2);
        g[z1][z2] = g[z2][z1] = z;
    }
    cin>>s;
    while(s--){
        cin>>x1>>y1>>z;
        key[get(x1,y1)] |= 1 << z;
    }
    cout<<bfs()<<endl;
    return 0;
}

7-62 前t个组合结果 (25 分)

#include <iostream>
using namespace std;

int n,r,t;
int m;
const int N = 31;

bool st[N];
int a[N];
void dfs(int num,int id)
{
    if(m >= t) return;
    
    if(id == r){
        for(int i = 0;i < r;i ++){
            cout << ' ' << a[i];
        }
        cout << endl;
        m ++;
        return;
    }
    if(num <= 0) return;
    a[id] = num;
    dfs(num - 1,id + 1);
    dfs(num - 1,id);
}

int main()
{
    while(cin >> n >> r >> t){
        m = 0;
        dfs(n,0);
        m = 0;
    }
    return 0;
}
/*
5 4 3  5 4 3
5 4 2 
5 4 1 
5 3 2 
5 3 1 
5 2 1 
4 3 2 
4 3 1 
4 2 1 
3 2 1 
*/

7-63 自然数拆分问题 (60 分)

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

int n,r,t;
int m;
const int N = 60;

bool st[N];
int a[N];
vector<int>vec;

void dfs(int num,int s)
{
    if(num == 0){
        cout << n << "=" << vec[0];
        for(int i = 1;i < vec.size();i ++){
            cout << "+" << vec[i];
        }
        cout << endl;
        return;
    }
    
    for(int i = s;i <= num;i ++){
        vec.push_back(i);
        dfs(num - i,i);
        vec.pop_back();
    }
    
}

int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    dfs(n,1);
    
    return 0;
}
/*
5 4 3  5 4 3
5 4 2 
5 4 1 
5 3 2 
5 3 1 
5 2 1 
4 3 2 
4 3 1 
4 2 1 
3 2 1 
*/

7-64 字母排列问题 (10 分)

#include <iostream>
#include <vector>
using namespace std;
int n,m;
string str;
bool st[30];

void dfs(int cnt)
{
    if(cnt == m){
        for(int i = 0;i < m;i ++){
            printf("%c",str[i]);
        }
        printf("\n");
        return;
    }
    
    for(int i = 0;i < n;i ++){
        char c = i + 'A';
        if(st[i]) continue;
        str = str + c;
        st[i] = true;
        dfs(cnt + 1);
        st[i] = false;
        str.pop_back();
    }
    
    
}

int main()
{
    scanf("%d%d",&n,&m);
    dfs(0);
    return 0;
}
/*
AB
AC
BA
BC
CA
CB
*/

7-65 八皇后问题 (20 分)

#include <stdio.h>  
#include <math.h>  
int queenPlaces[92][8]; //存放92种皇后棋子的摆放方法  
int count = 0;  
int board[8][8]; //仿真棋盘  
void putQueen(int ithQueen); //递归函数,每次摆好一个棋子  

int main()  
{  
   int n, i, j;    
    for(i = 0; i < 8; i++){  // 初始化  
        for(j = 0; j < 8; j++)  
            board[i][j] = -1;  
        for(j = 0; j < 92; j++)  
            queenPlaces[j][i] = 0;  
    }  
    putQueen(0); //从第0个棋子开始摆放,运行的结果是将queenPlaces生成好  
   scanf("%d", &n);  
   for(i = 0; i < n; i++){  
        int ith;  
        scanf("%d", &ith);  
        for(j = 0; j < 8; j++)  
           printf("%d", queenPlaces[ith - 1][j]);  
        printf("\n");  
    }  
}  
void putQueen(int ithQueen){  
     int i, k, r;  
     if(ithQueen == 8){  
         count ++;  
         return;  
     }  
     for(i = 0; i < 8; i++){  
         if(board[i][ithQueen] == -1){  
             //摆放皇后  
             board[i][ithQueen] = ithQueen;  
             //将其后所有的摆放方法的第ith个皇后都放在i+1的位置上  
             //在i增加以后,后面的第ith个皇后摆放方法后覆盖此时的设置  
             for(k = count; k < 92; k++)  
                 queenPlaces[k][ithQueen] = i + 1;  
             //设置控制范围  
             for(k = 0; k < 8; k++)  
             for(r = 0; r < 8; r++)  
                 if(board[k][r] == -1 &&   
                     (k == i || r == ithQueen || abs(k - i) == abs(r - ithQueen)))   
                     board[k][r] = ithQueen;  
             //向下级递归  
             putQueen(ithQueen + 1);  
             //回溯,撤销控制范围  
             for(k = 0; k < 8; k++)  
             for(r = 0; r < 8; r++)  
                     if(board[k][r] == ithQueen) board[k][r] = -1;  
         }  
     }  
}  


7-66 旅行售货员 (10 分)

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

using namespace std;

int n;
vector<int> path;
const int N = 10;

int g[N][N];
int ans = 0x3f3f3f3f;

void dfs(int u, int state)
{
    if (u == n)
    {
        int sum = 0;
        
        for(int i = 0;i < path.size() - 1;i ++){
            sum += g[path[i]][path[i + 1]];
        }
        sum += g[path[path.size() - 1]][path[0]];
        
        // cout << endl;
        ans = min(ans,sum);
        return;
    }

    for (int i = 0; i < n; i ++ )
        if (!(state >> i & 1))
        {
            path.push_back(i + 1);
            dfs(u + 1, state + (1 << i));
            path.pop_back();
        }
}

int main()
{
    cin >> n;
    for(int i = 1;i <= n;i ++)
        for(int j = 1;j <= n;j ++)
                cin >> g[i][j];
    
    dfs(0, 0);
    
    cout << ans << endl;
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值