大三上算法课pintia复习

7-1 最大公约数

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

long fun(long m, long n) {
	long y;	
	while (n > 0) {
		y = m % n;
		m = n;
		n = y;
	}
	return m;					
}
int main() {
	long n, m;
	cin >> m >> n;
	cout << fun(m, n);
	return 0;
}

7-2 百钱百鸡

#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
#include<stdio.h>

int main() {
	for (int i = 0; i <= 20; i++) {
		for (int j = 0; j <= 33; j++) {
			for (int k = 0; k <= 99;k+=3) {
				if ((i + j + k == 100 )&& (5 * i + 3 * j + k / 3 == 100)) {
					printf("cock=%d,hen=%d,chicken=%d\n", i, j, k);
				}
			}
		}
	}
	return 0;
}

7-3 国王的奖励(暴力版)

#include<iostream>
#include<cstdio>
using namespace std;
#include <stdio.h>
#include<math.h>
#include<cmath>

const int mod = 100000007;

int main() {
    int t = 0;
    cin >> t;
    for (int i = 0; i < t; i++) {
        int q, n;
        cin >> q >> n;
        long ans = 1;
        long jia = 1;
        while (--n>0) {
            jia *= q;
            jia %= mod;
            ans += jia;
            ans %= mod;     
        }
        cout << ans << endl;
    }

    return 0;
}

7-4 powmod(暴力版)

#include<iostream>
#include<cstdio>
using namespace std;
#include <stdio.h>
#include<math.h>
#include<cmath>

int qumo(int a, int b, int m)
{
 if (b == 0) return 1;
 int x = qumo(a, b / 2, m);
 int ans = (int)x * x % m;
 if (b % 2 == 1) ans = ans * a % m;
 return (int)ans;
}

int main() {
 int a, b, m;
 cin >> a >> b >> m;
 cout<<qumo(a, b, m);
}

7-5 平面最近点对(暴力版)

#include<iostream>
#include<cstdio>
using namespace std;
#include <stdio.h>
#include<math.h>
#include<cmath>

int main(){
    int n = 0;
    cin >> n;
    int a[100000][2];
    for (int i = 0; i < n; i++) {
        int x;
        int y;
        cin >> x >> y;
        a[i][0] = x;
        a[i][1] = y;
    }
    long ans = 10000000000;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int x1 = a[i][0];
            int y1 = a[i][1];
            int x2 = a[j][0];
            int y2 = a[j][1];
            long now = pow(x1 - x2, 2) + pow(y1 - y2, 2);
            if (ans > now) {
                ans = now;
            }
        }
    }
    double ansD = sqrt(ans);
    printf("%.4f", ansD);
    return 0;
}

7-6 国王的奖励(分治版)

#include<stdio.h>
#include<iostream>
using namespace std;
#define mod 100000007

long long qmul(long long a,long long b){
    a = (a % mod + mod) % mod;
    b = (b % mod + mod) % mod;
    long long c = a * (long double)b / mod;
    long long ans = a * b - c * mod;
    if(a < 0){
        a += mod;
    }else if(a >= mod){
        a -= mod;
    }
    return ans;
}
long long qpow(long long base,long long power){
    base %= mod;
    long long ans = 1;
    while(power){
        if(power & 1){
            ans = qmul(ans,base);
        }
        base = qmul(base,base);
        power >>= 1;
    }
    return ans;
}
long long sum(long long q,long long n){
    if(n == 1){
        return 1;
    }
    if(n & 1){
        return (qmul(1 + qpow(q,n >> 1), sum(q, n >> 1)) + qpow(q,n-1)) % mod;
    }
    else{
        return qmul(1 + qpow(q,n >> 1), sum(q, n >> 1));
    }
}
int main(){
    int m;
    cin >> m;
    long long q,n;
    while(m--){
        cin >> q >> n;
        if(q == 1){
            cout <<n % mod << endl;
        }else{
            cout << sum(q, n) << endl;
        }
    }
    return 0;
}

7-7 powmod(分治版)

#include<iostream>
#include<math.h>
using namespace std;

int main(void){
	long long a, n, m;
	cin >> a >> n >> m;
	a %= m;
	long long ans = 1;
	while (n) {
		if (n & 1) {
			ans = (ans * a) % m;
		}
		a = (a * a) % m;
		n >>= 1;
	}
	cout << ans;
	return 0;
}

7-8 平面最近点对(分治版)

#include<iostream>
#include<algorithm>
#include<cmath>
#include<stdio.h>
using namespace std;

const int m = 200003;

class node{
public:
    double x;
    double y;
    node(){
        
    }
    node(double x, double y){
        this -> x = x;
        this -> y = y;
    }
};

node s[m];
node p[m];

int cmp(node a, node b){
    return a.y < b.y;
}
double distance(node a,node b){
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y-b.y));
}
double close(node s[],int l,int r){
    double d1, d2, d3, d;
    if(r-l == 1){
        return distance(s[l],s[r]);
    }
    if(r - l == 2){
        d1 = distance(s[l], s[r]);
        d2 = distance(s[l], s[l+1]);
        d3 = distance(s[r-1], s[r]);
        if(d1<d2)d=d1;
        else d=d2;
        if(d3<d)d=d3;
        return d;
    }
    int index=0;
    int mid=l+(r-l)/2;
    d1=close(s,l,mid);
    d2=close(s,mid+1,r);
    if(d1<d2)d=d1;
    else d=d2;
    for(int i=mid;i>=l&&s[mid].y-s[i].y<d;i--){
        p[index++]=s[i];
    }
    for(int j=mid+1;j<=r&&s[j].y-s[mid].y<d;j++){
        p[index++]=s[j];
    }
    sort(p,p+index,cmp);
    for(int i=0;i<index;i++){
        for(int j=i+1;j<index;j++){
            if(p[j].y-p[i].y>d){
                break;
            }
            d3=distance(p[j],p[i]);
            if(d3<d)d=d3;
        }
    }
    return d;
}
int main(){
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>s[i].x>>s[i].y;
    }
    sort(s,s+n,cmp);
    double ans=close(s,0,n-1);
    printf("%.4f",ans);
}

7-9 最大子段和(分治版)

#include<iostream>
#include<algorithm>
#include<cmath>
#include<stdio.h>
using namespace std;

const int m = 210003;

int s[m];
int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> s[i];
	}
	bool flag = true;
	for (int i = 0; i < n; i++) {
		if (s[i] >= 0)flag = false;
	}
	if (flag) {
		cout << 0;
		return 0;
	}
	int pre = s[0];
	int ans = s[0];
	for (int i = 1; i < n; i++) {

		if (pre + s[i] > s[i]) {
			pre += s[i];
		}
		else {
			pre = s[i];
		}
        if (ans < pre)ans = pre;
		
	}
	cout << ans;
	return 0;
}

7-10 起泡排序

#include<iostream>
long long ans = 0;
#define int long long
#define N 200001
using namespace std;

int a[N], b[N];

void Merge(int left, int mid, int right)
{
	int i = left, j = mid + 1, k = left;
	while (i <= mid && j <= right)
	{
		if (a[i] <= a[j])
		{
			b[k++] = a[i++];//将a[i],a[j]中较小者放入b[k]
		}
		else
		{
			b[k++] = a[j++];
			ans += mid - i + 1;
		}
	}
	while (i <= mid)
		b[k++] = a[i++];
	while (j <= right)
		b[k++] = a[j++];
	for (long long i = left; i <= right; i++)
		a[i] = b[i];//将有序序列换回来
}
void MergeSort(int left, int right)
{
	int mid;
	if (left >= right)
		return;
	else
	{
		mid = (left + right) / 2;
		MergeSort(left, mid);
		MergeSort(mid + 1, right);
		Merge(left, mid, right);
	}
}
signed main()
{
	int n;
	cin >> n;
	for (long long i = 0; i < n; i++)
		cin >> a[i];
	MergeSort(0, n - 1);
	cout << ans;
}

7-11 棋盘覆盖问题

#include<iostream>
#include<iomanip>
#include<cstdio>
#include <stdio.h>
#include<math.h>
#include<cmath>
using namespace std;

int boardSize;
int count = 1;
int board[100][100];

void chessboard(int tr, int tc, int dr, int dc, int size)
{
    if (size == 1)//递归结束
    {
        return;
    }
    int t = count++;
    int s = size / 2;
    if (dr < tr + s && dc < tc + s)//如果在左上角部分
    {
        chessboard(tr, tc, dr, dc, s);
    }
    else
    {
        board[tr + s - 1][tc + s - 1] = t;
        chessboard(tr, tc, tr + s - 1, tc + s - 1, s);
    }
    if (dr < tr + s && dc >= tc + s)
    {
        chessboard(tr, tc + s, dr, dc, s);
    }
    else
    {
        board[tr + s - 1][tc + s] = t;
        chessboard(tr, tc + s, tr + s - 1, tc + s, s);
    }


    if (dr >= tr + s && dc < tc + s)//如果在右上角
    {
        chessboard(tr + s, tc, dr, dc, s);
    }
    else
    {
        board[tr + s][tc + s - 1] = t;
        chessboard(tr + s, tc, tr + s, tc + s - 1, s);
    }
    if (dr >= tr + s && dc >= tc + s)//如果在右下角部分
    {
        chessboard(tr + s, tc + s, dr, dc, s);   
    }
    else
    {
        board[tr + s][tc + s] = t;
        chessboard(tr + s, tc + s, tr + s, tc + s, s);
    }

}



int main() {

cout.flags (ios::left);
	cin>>boardSize; 
	int dr,dc;
	cin>>dr>>dc;
    chessboard(0, 0, dr, dc, boardSize);
    for (int i = 0; i < boardSize; i++)
    {
        for (int j = 0; j < boardSize; j++)
        {
            cout <<setw(5)<< board[i][j];
        }
        cout << endl;
    }
    return 0;
}

7-12 逆序对

#include<iostream>
using namespace std;
const int n=1000009;
int a[n];
int b[n];
long long ans=0;
void merge(int l,int m,int r){
    int i,j,p;
    i=l;
    j=m;
    p=l;
    while(i<m&&j<=r){
        if(a[i]<=a[j]){
            b[p++]=a[i++];
        }else{
            ans+=m-i;
            b[p++]=a[j++]; 
        }
    }
    while(i<m){
        b[p++]=a[i++];
    }
    while(j<=r){
        b[p++]=a[j++];
    }
    i=l;
    p=l;
    while(p<=r){
        a[i++]=b[p++];
    }
}

void merge_sort(int l,int r){
    if(l<r){
        int m=(l+r)/2;
        merge_sort(l,m);
        merge_sort(m+1,r);
        merge(l,m+1,r);
    }
    
}
int main(){
    int m;
    cin>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    merge_sort(1,m);
    cout<<ans;
}

7-13 铺设油井管道

#include <stdio.h>
#include <stdlib.h>
#include<math.h>
int n;
int a[1001010];
int k;
int mid;
void fid(int left,int right)
{
    int temp=a[left];
    int i=left;
    int j=right;
    if(i>j)
        return;
    while(i<j)
    {
        while(i<j&&a[j]>temp)
            j--;
        a[i]=a[j];
        while(i<j&&a[i]<=temp)
            i++;
        a[j]=a[i];
    }
    a[i]=temp;
    if(i==k)
        mid=a[i];
    else if(i>k)
        fid(left,i-1);
    else
        fid(i+1,right);
    return ;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d%d",&x,&a[i]);
    }
    if(n%2==0)
        k=n/2;
    else
        k=n/2+1;
    fid(1,n);
    long long sum=0;
    for(int i=1;i<=n;i++)
        sum+=abs(a[i]-mid);
    printf("%lld",sum);
    return 0;
}

7-14 铺设油井管道plus

#include <stdio.h>
#include <stdlib.h>
#include<math.h>
int n;
int a[2001000];
int k;
int mid;
void fid(int left,int right)
{
    int temp=a[left];
    int i=left;
    int j=right;
    if(i>j)
        return;
    while(i<j)
    {
        while(i<j&&a[j]>temp)
            j--;
        a[i]=a[j];
        while(i<j&&a[i]<=temp)
            i++;
        a[j]=a[i];
    }
    a[i]=temp;
    if(i==k)
        mid=a[i];
    else if(i>k)
        fid(left,i-1);
    else
        fid(i+1,right);
    return ;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d%d",&x,&a[i]);
    }
    if(n%2==0)
        k=n/2;
    else
        k=n/2+1;
    fid(1,n);
    long long sum=0;
    for(int i=1;i<=n;i++)
        sum+=abs(a[i]-mid);
    printf("%lld",sum);
    return 0;
}

7-15 最大子段和(动态规划版)

#include<stdio.h>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int n = 1000000;
int a[n];
int main() {
    int n;
    scanf("%d", &n);
    int f;
    scanf("%d", &f);
    int p = f;
    int ans = f;
    bool flag = true;
    for (int i = 1; i < n; i++) {
        int t;
        scanf("%d", &t);
        if (flag && t > 0)flag = false;

        if (p + t > t) {
            p += t;
        }
        else {
            p = t;
        }
        if (p > ans)ans = p;
    }
    if (flag) {
        printf("0\n");
        return 0;
    }
    printf("%d\n", ans);
    return 0;
}

7-16 最大子段和(数据加强)

#include<iostream>
#include<stdio.h>
using namespace std;

struct gen
{
    int seed, mul, bias, mod;
    int get()
    {
        seed = (seed * mul + bias) % mod;
        return seed - (mod / 2);
    }
};

int n;
int a[100000001];
int main()
{
    cin >> n;
    gen g;
    cin >> g.seed >> g.mul >> g.bias >> g.mod;
    int sum=0;
    int ans=0;
    for (int i = 1; i <= n; i++)
    {
        a[i] = g.get();
        if(sum+a[i]>a[i]){
            sum+=a[i];
        }else{
            sum=a[i];
        }
        if(sum<0)sum=0;
        if(ans<sum)ans=sum;
    }
    // a数组即为题目给出的数组
    printf("%d\n",ans);
    return 0;
}

7-17 数塔

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

const int N = 103;
int a[N][N];

int DataTower(int d[N][N],int n) {
	int maxAdd[N][N] = { 0 };
	int i, j;
	for (j = 0; j < n; j++) {
		maxAdd[n - 1][j] = d[n - 1][j];
	}
	for (i = n - 2; i >= 0; i--) {
		for (j = 0; j <= i; j++) {
			if (maxAdd[i + 1][j] > maxAdd[i + 1][j + 1]) {
				maxAdd[i][j] = d[i][j] + maxAdd[i + 1][j];
			}
			else {
				maxAdd[i][j] = d[i][j] + maxAdd[i + 1][j + 1];
			}
		}
	}
	/*
	printf("路径为:%d", d[0][0]);
	j = path[0][0];
	for (i = 1; i < n; i++) {
		printf("-->%d", d[i][j]);
		j = path[i][j];
	}
	*/
	return maxAdd[0][0];
}
int main() {
	int c;
	cin >> c;
	while (c-- > 0) {
		int n;
		cin >> n;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j <= i; j++) {
				cin >> a[i][j];
			}
		}
		int ans = DataTower(a, n);
		cout << ans << endl;
	}
	return 0;
}

7-18 最短路径

#include <iostream>
#include<algorithm>
#include<cmath>
using namespace std;
//2147483647
const int m = 100000000;
const int N = 1003;
int arc[N][N];
int vnum = 0;
int CreatGraph() {
	int i, j, k;
	int weight;
	int arcnum;//顶点,边
	cin >> vnum >> arcnum;
	for (i = 0; i < vnum; i++) {
		for (j = 0; j < vnum; j++) {
			arc[i][j] = m;
		}
	}
	for (k = 0; k < arcnum; k++) {
		cin >> i >> j >> weight;
		arc[--i][--j] = weight;
	}
	return vnum;
}
int BackPath(int n) {
	int i, j, temp;
	int cost[N];
	for (i = 1; i < n; i++) {
		cost[i] = m;

	}
	cost[0] = 0;

	for (j = 1; j < n; j++) {
		for (i = j - 1; i >= 0; i--) {
			if (arc[i][j] + cost[i] < cost[j]) {
				cost[j] = arc[i][j] + cost[i];
			}
		}
	}
	return cost[n - 1];
}
int main() {
	CreatGraph();
	cout<< BackPath(vnum);

	return 0;
}

第二种解法

#include<iostream>
#include<iomanip>
using namespace std;
const int M = 0x3f3f3f;
const int m = 1003;
int a[m][m];
int main() {
    int n;
    cin >> n;
    int b;
    cin >> b;
    for (int i = 0; i < b; i++) {
        int r, c, v;
        cin >> r >> c >> v;
        a[c-1][r-1] = v;
    }
    for (int i = 1; i < n; i++) {
        int nm = M;
        for (int j = 0; j < n; j++) {
            if (a[i][j] != 0 && a[i][j] + a[j][0] < nm) {
                nm = a[i][j] + a[j][0];
            }
        }
        a[i][0] = nm;
    }
    cout << a[n - 1][0] ;
    return 0;
}

7-19 排序问题

#include<iostream>
#include<stdio.h>
using namespace std;
const int m=105;
int a[m];
void shift(int a[],int k,int n){
    int i,j,t;
    i=k;
    j=2*i+1;
    while(j<n){
        if(j<n-1&&a[j]<a[j+1])j++;
        if(a[i]>a[j])break;
        else{
            t=a[i];
            a[i]=a[j];
            a[j]=t;
            i=j;
            j=2*i+1;
        }
    }
}
void heapSort(int a[],int n){
    int t;
    for(int i=(n-1)/2;i>=0;i--){
        shift(a,i,n);
    }
    for(int i=1;i<n;i++){
        t=a[0];
        a[0]=a[n-i];
        a[n-i]=t;
        shift(a,0,n-i);
    }
}


int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
    }
    heapSort(a,n);
    for(int i=0;i<n;i++){
        printf("%d ",a[i]);
    }
}

7-20 旅行商问题


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

class Tsp {
private:
	int n;
	int** d;
	int** p;
public:
	Tsp(int num);
	void s();
	
};

Tsp::Tsp(int num) {
	n = num;
	d = new int* [n];
	for (int i = 0; i < n; i++) {
		d[i] = new int[n];
		for (int j = 0; j < n; j++) {
			scanf("%d", &d[i][j]);
		}
	}
	/*
	* 	cout << "输入的矩阵为:" << endl;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cout << d[i][j] << " ";
		}
		cout << endl;
	}
	cout << endl;
	*/

	p = new int* [n];
	for (int i = 0; i < n; i++) {
		p[i] = new int[1 << (n - 1)];
	}
}
void Tsp::s() {
	for (int i = 0; i < n; i++) {
		p[i][0] = d[i][0];
	}
	for (int i = 1; i < 1 << (n - 1); i++) {
		for (int j = 0; j < n; j++) {
			p[j][i] = 0x3f3f3f3f;
			if ((i>>(j-1) & 1) == 1)continue;
			for (int k = 1; k < n; k++) {
				if ((i>> (k - 1) & 1) == 0)continue;
				if (p[j][i] > d[j][k] + p[k][i ^ (1 << (k - 1))]) {
					p[j][i] = d[j][k] + p[k][i ^ (1 << (k - 1))];
				}
			}
		}
	}
	printf("%d\n", p[0][(1 << (n - 1))-1]);
}
int main() {
	int n;
	scanf("%d", &n);
	int no;
	cin >> no;
	Tsp t = Tsp(n);
	t.s(); 
	return 0;
}

7-21 最短路径算法(Floyd-Warshall)

#include<iostream>
#define INF 9999999
using namespace std;
const int N = 53;

void display(int dist[N][N], int n)
{

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            if (dist[i][j] >= INF) {
                cout << -1 << " ";
            }
            else {
                cout << dist[i][j] << " ";
            }
        cout << endl;
    }

}

void Floyd(int arc[N][N], int dist[N][N],int n)
{
    int i, j, k;
    
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            dist[i][j] = arc[i][j];
        }
    }

    for (k = 0; k < n; k++)
    {

        for (i = 0; i < n; i++)
        {
            for (j = 0; j < n; j++)
            {
                if (dist[i][k] + dist[k][j] < dist[i][j])

                {

                    dist[i][j] = dist[i][k] + dist[k][j];

                }
            }
        }
    }

}

int main(void)
{
    int static arc[N][N];
    int static dist[N][N] ;

    int n;
    cin >> n;
    
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {

            cin >> arc[i][j];
            if (i != j && arc[i][j]==0) {
                arc[i][j] = INF;
            }
        }
    }
    

    Floyd(arc, dist,n);

    display(dist,n);

    return 0;
}

7-22 最长有序子序列

#include<iostream>
using namespace std;
const int m=1001;
int a[m];
int l[m];
int n;
int f(){
    for(int i=0;i<n;i++){
        int max=1;
        for(int j=i-1;j>=0;j--){
            if(a[j]<a[i]&&l[j]+1>max){
                max=l[j]+1;
                l[i]=max;
            }
        }
    }
    int index=0;
    for(int i=1;i<n;i++){
        if(l[index]<l[i]){
            index=i;
        }
    }
    return l[index];
}
int main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>a[i];
            l[i]=1;
        }
        cout<<f()<<endl;
        if(t)cout<<endl;
    }
}

7-23 最长公共子序列长度

#include<iostream>
using namespace std;
const int m = 100;
char a[m];
char b[m];
int d[m][m];
int main() {
    cin >> a;
    
    int la = 0;
    for (char i : a) {
        if (i != NULL)la++;
        else break;
    }



    cin >> b;
    int lb = 0;
    for (char i : b) {
        if (i != NULL)lb++;
        else break;
    }

    for (int i = 0; i < m; i++) {
        d[i][0] = 1;
        d[0][i] = 1;
    }
    for (int i = 0; i < la; i++) {
       
        for (int j = 0; j < lb; j++) {
            
            if (a[i] != b[j]) {
                d[i + 1][j + 1] = max(d[i][j + 1], d[i + 1][j]);
            }
            else {
                d[i + 1][j + 1] = d[i][j] + 1;
            }
        }
    }
    cout << d[la][lb]-1;
    return 0;
}

7-24 0-1背包

#include<iostream>
using namespace std;
int f[1001];
int v[105];
int w[105];
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=m;j>=w[i];j--){
            f[j]=max(f[j],f[j-w[i]]+v[i]);
        }
    }
    cout<<f[m];
    return 0;
}

7-25 最优二叉搜索树

#include<iostream>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
const int M = 100;
double C[M][M], W[M][M], p[M], q[M];
int S[M][M];
int n, i, j, k;
void Optimal_BST()
{
    for (i = 1; i <= n; i++)
    {
        C[i][i - 1] = 0.0;
        W[i][i - 1] = q[i - 1];
    }
    for (int t = 1; t <= n; t++)
    {
        for (i = 1; i <= n - t + 1; i++)
        {
            j = i + t - 1;
            W[i][j] = W[i][j - 1] + p[j] + q[j];
            C[i][j] = C[i][i - 1] + C[i + 1][j];
            S[i][j] = i;
            // 选取i+1到j之间的某个下标的关键字作为i到j的根,如果组成的期望值最小
            // 则k为i到j的根结点
            for (k = i + 1; k < j; k++)
            {
                double tmp = C[i][k - 1] + C[k + 1][j];
                if (tmp < C[i][j] && fabs(tmp - C[i][j])>1E-6)
                {
                    C[i][j] = tmp;
                    S[i][j] = k;  // 记录i到j结点的树根
                }
            }
            C[i][j] += W[i][j];
        }
    }
}
void Construct_Optimal_BST(int i, int j, bool flag)
{
    if (flag == 0)
    {
        cout << S[i][j] << " ";;
        flag = 1;
    }
    int k = S[i][j];
    // 如果左子树是叶子
    if (k - 1 < i)
    {
        cout << "." << " ";;
    }
    else
    {
        cout << S[i][k - 1] << " ";;
        Construct_Optimal_BST(i, k - 1, 1);
    }
    // 如果右子树是叶子
    if (k >= j)
    {
        cout << "." << " ";;
    }
    else
    {
        cout << S[k + 1][j] << " ";;
        Construct_Optimal_BST(k + 1, j, 1);
    }
}
int main()
{
    cin >> n;

    for (i = 1; i <= n; i++)
    {
        cin >> p[i];
    }

    for (i = 0; i <= n; i++)
    {
        cin >> q[i];
    }
    Optimal_BST();
    cout << fixed << setprecision(2) << C[1][n] << endl;

    Construct_Optimal_BST(1, n, 0);
    system("pause");
    return 0;
}

7-26 选课(贪心)

#include<iostream>
#include<algorithm>
using namespace std;
const int m = 10009;
pair<double,double> a[m];
char b[m];

int cmp(pair<double, double> a, pair<double, double>b) {
    return a.second < b.second;
}
int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> b;
        cin >> a[i].first;
        cin >> a[i].second;
    }
   
    sort(a, a+n, cmp);


    int ans = 1;
    double j = a[0].second;
    for (int i = 1; i < n; i++) {   
        if (a[i].first >= j) {
            j = a[i].second;
            ans += 1;
        }

    }
    cout << ans << endl;
    return 0;
}

7-27 汉密尔顿回路

#include<bitset>
#include<iostream>
#include<cstring>
using namespace std;
 
int a[210][210];
int b[210];
int c[210];
int main() {
	int n, m;
	cin >> n >> m;
	//输入边
	for (int i = 0; i < m; i++) {
		int x, y;
		cin >> x >> y;
		a[x][y] = a[y][x]= 1;
	}
	int p;
	cin >> p;
	//int v = 0;
	while (p--) {
		int q;//一次测验几个点检验
		cin >> q;
		
		bool flag = true;
		//memset(c, false, sizeof(c));
		memset(c, 0, sizeof(c));
		
		for (int i = 1; i < q; i++) {
			int t;
			cin >> t;
			b[i] = t;
			if (t<1 || t>n) {
				flag = false;
				//cout << "不合格点" << endl;
			}

			if (c[t] == 1) {
				//cout << "有重复的" << endl;
				flag = false;
			}
			c[t]=1;
		}

		cin >> b[q];
		//没有走过所有点
		if (q != n + 1)flag = false;
		//cout << "访问数组c为:";
		//for (int i = 1; i <= q; i++) {
		//	cout << c[i] << " ";
		//}
		//cout << endl;
		//cout << "输入数组为:" ;
		//for (int i = 1; i <= q; i++) {
		//	cout << b[i] << " ";
		//}
		//cout << endl;
		//检验是否有0
		
		if (b[1] != b[q]) {
			//cout << "首尾不一样" << endl;
			flag = false;
		}
		for (int i = 2; i <= q; i++) {
			if (a[b[i]][b[i-1]] != 1) {
				flag = false;
				//cout << "有不连通的两个点" << endl;
			}
		}
		//cout << flag ? "YES" : "NO" << endl;
		if (flag) {
			cout << "YES" << endl;
		}
		else {
			cout << "NO" << endl;
		}
		
	}
	return 0;
}

7-28 八皇后问题(*)

#include<iostream>
#include<algorithm>
using namespace std;
int n, * x;     //x[]皇后在每一行的位置
bool b=false;    //判断有没有解
bool constraint(int k)
{
	for (int j = 0; j < k; j++)
		if ((abs(x[j] - x[k]) == abs(j - k)) || (x[j] == x[k]))  //判断是否在同一斜线或同一列
			return false;
	return true;
}
void backtrack(int k)
{
	int i;
	if (k >= n)
	{
        if(b)
            cout<<endl;
		b = true;
		for (int j, i = 0; i < n; i++)
		{
			for (j = 0; j < n-1; j++)
			{
				if (x[i] == j)
					cout << "Q ";
				else cout << ". ";
			}
            if (x[i] == j)
                cout << "Q";
            else cout << ".";
			cout << endl;
		}
	}
	else
	{
		for (i = 0; i < n; i++)
		{
			x[k] = i;
			if (constraint(k))
				backtrack(k + 1);
		}
	}
}
int main()
{
	cin >> n;
	x = new int[n];
	backtrack(0);
	if (!b)
		cout << "None" << endl;
	delete[] x;
	return 0;
}

7-29 任务分配

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int n;
const int INF=0x3f3f3f3f;
const int mn=21;
int a[mn][mn];
int ans=INF;
class node{
  public:
    int r;
    int c;
    int l;
    bool w[mn];
    bool operator<(const node&s)const{
        return l>s.l;
    }
};

void b(node & e){
    int m=0;
    for(int i=e.r+1;i<=n;i++){
        int nmin=INF;
        for(int j=1;j<=n;j++){
            if(e.w[j]==false&&nmin > a[i][j]){
                nmin=a[i][j];
            }
            
        }
       m+=nmin;
    }
    e.l=e.c+m;
}

void bfs(){
    node e,e1;
    e.c=0;
    memset(e.w,0,sizeof(e.w));
    e.r=0;
    b(e);
    priority_queue<node>q;
    q.push(e);
    while(!q.empty()){
        e=q.top();
        q.pop();
        if(e.r==n){
            if(ans>e.c){
                ans=e.c;
            }
        }
        e1.r=e.r+1;
        
        for(int i=1;i<=n;i++){
            if(e.w[i]){
                continue;
            }
            for(int j=1;j<=n;j++){
                e1.w[j]=e.w[j];
            }
            e1.w[i]=true;
            e1.c=e.c+a[e1.r][i];
            b(e1);
            if(e1.l<ans){
                q.push(e1);
            }
        }
    }
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>a[i][j];
        }
    }
    bfs();
    cout<<ans<<endl;
    return 0;
}

7-30 吉林跑男

判断是否是二分图(是NO,否YES)

#include<bits/stdc++.h>
using namespace std;
const int maxn=10000005;
int father[maxn];
int findset(int x)//并查集路径压缩
{
    if(x!=father[x]) father[x]=findset(father[x]);
    return father[x];
}
int main(){
    int t;
    cin>>t;
   while(t--){
        
    
    int n,m;

    cin>>n>>m;
    
        for(int i=1;i<=2*n;i++) father[i]=i;
        bool flag=true;
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            int fa=findset(u);//查找根节点
            int fb=findset(v);
            int x=findset(u+n);//查找u不认识的人的根节点
            int y=findset(v+n);
            if(fa==fb) flag=false;
            else//将两个不认识的人合并在同一个集合中
            {
                father[x]=fb;
                father[y]=fa;
            }
        }
        if(flag) printf("NO\n");
        else     printf("YES\n");
    }
    return 0;
}

  • 14
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值