zoukankan      html  css  js  c++  java
  • ACM2作业

    文件读写知识点:

    写入文件:freopen("文件名", "r", stdin);
    写出文件:freopen("文件名", "w", stdout);

    不解释,上代码:

    1、Dijkstra算法求最短路径。

    #include<iostream>
    #include<string>
    #include<cstring>
    using namespace std;
    
    //记录起点到每个顶点的最短路径的信息
    struct Dis {
    	string path;
    	int value;
    	bool visit;
    	Dis() {
    		visit = false;
    		value = 0;
    		path = "";
    	}
    };
    
    class Graph_DG {
    private:
    	int vexnum;   //图的顶点个数
    	int edge;     //图的边数
    	int **arc;   //邻接矩阵
    	Dis * dis;   //记录各个顶点最短路径的信息
    public:
    	//构造函数
    	Graph_DG(int vexnum, int edge);
    	//析构函数
    	~Graph_DG();
    	//顶点从1开始编号
    	bool check_edge_value(int start, int end, int weight);
    	//创建图
    	void createGraph();
    	//求最短路径
    	void Dijkstra(int begin);
    	//打印最短路径
    	void print_path(int);
    };
    
    Graph_DG::Graph_DG(int vexnum, int edge) {
    	//初始化顶点数和边数
    	this->vexnum = vexnum;
    	this->edge = edge;
    	//为邻接矩阵开辟空间和赋初值
    	arc = new int*[this->vexnum];
    	dis = new Dis[this->vexnum];
    	for (int i = 0; i < this->vexnum; i++) {
    		arc[i] = new int[this->vexnum];
    		for (int k = 0; k < this->vexnum; k++) {
    			//邻接矩阵初始化为无穷大
    			arc[i][k] = INT_MAX;
    		}
    	}
    }
    //析构函数
    Graph_DG::~Graph_DG() {
    	delete[] dis;
    	for (int i = 0; i < this->vexnum; i++) {
    		delete this->arc[i];
    	}
    	delete arc;
    }
    //顶点从1开始编号
    bool Graph_DG::check_edge_value(int start, int end, int weight) {
    	if (start<2 || end<2 || start>vexnum || end>vexnum || weight < 0) {
    		return false;
    	}
    	return true;
    }
    
    void Graph_DG::createGraph()
    {
    	//cout << "请输入每条边的起点和终点(顶点编号从s开始)以及其权重" << endl;
    	int start,end,weight,count=0;
    	while (count != this->edge) {
    		cin >> start >> end >> weight;
    		//对邻接矩阵对应上的点赋值
    		arc[start - 1][end - 1] = weight;
    		++count;
    	}
    }
    
    void Graph_DG::Dijkstra(int begin) {
    	//首先初始化我们的dis数组
    	int i;
    	for (i = 0; i < this->vexnum; i++) {
    		//设置当前的路径
    		//dis[i].path = "v" + to_string(begin) + "-->v" + to_string(i + 1);
    		dis[i].path = to_string(begin) + " " + to_string(i + 1);
    		dis[i].value = arc[begin - 1][i];
    	}
    	//设置起点的到起点的路径为0
    	dis[begin - 1].value = 0;
    	dis[begin - 1].visit = true;
    
    	int count = 1;
    	//计算剩余的顶点的最短路径(剩余this->vexnum-1个顶点)
    	while (count != this->vexnum) {
    		//temp用于保存当前dis数组中最小的那个下标
    		//min记录的当前的最小值
    		int temp = 0;
    		int min = INT_MAX;
    		for (i = 0; i < this->vexnum; i++) {
    			if (!dis[i].visit && dis[i].value<min) {
    				min = dis[i].value;
    				temp = i;
    			}
    		}
    		//cout << temp + 1 << "  "<<min << endl;
    		//把temp对应的顶点加入到已经找到的最短路径的集合中
    		dis[temp].visit = true;
    		++count;
    		for (i = 0; i < this->vexnum; i++) {
    			//注意这里的条件arc[temp][i]!=INT_MAX必须加,不然会出现溢出,从而造成程序异常
    			if (!dis[i].visit && arc[temp][i] != INT_MAX && (dis[temp].value + arc[temp][i]) < dis[i].value) {
    				//如果新得到的边可以影响其他为访问的顶点,那就就更新它的最短路径和长度
    				dis[i].value = dis[temp].value + arc[temp][i];
    				dis[i].path = dis[temp].path + " " + to_string(i + 1);
    			}
    		}
    	}
    
    }
    void Graph_DG::print_path(int begin)
    {
    	for (int i = 0; i != this->vexnum; i++)
    	{
    		if (dis[i].value != INT_MAX)
    		{
    			cout<< dis[i].value << endl;
    		}
    		else {
    			cout << "Infinite" << endl;
    		}
            cout << dis[i].path << endl;
    	}
    }
    
    bool check(int Vexnum, int edge) {
    	if (Vexnum <= 0 || edge <= 0 || ((Vexnum*(Vexnum - 1)) / 2) < edge)
    		return false;
    	return true;
    }
    
    int main()
    {
    	//freopen("Dijkstra_in.txt", "r", stdin);
    	//freopen("Dijkstra_out.txt", "w", stdout);
    	int t;
    	cin >> t;
    	while (t--)
    	{
           int vexnum,edge,s;
    	   cin >> vexnum >> edge >> s;
    	   Graph_DG graph(vexnum, edge);
    	   graph.createGraph();
    	   graph.Dijkstra(s);
    	   graph.print_path(s);
    	   system("pause");
    	}
    	return 0;
    }

    2、Prim算法求最小生成树。

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #define maxn 100
    #define inf  0x3f3f3f3f
    
    using namespace std;
    
    int i,j,G[maxn+1][maxn+1];//构建的图,必须是一个无向连通赋权图,G[i][j]存取权值*/
    int intree[maxn];//结点i在最小生成树中*/
    int minw[maxn];//到i点的最小权重*/
    int sumw;
    
    void init()
    {
    	memset(intree,0,sizeof(intree));
    	memset(minw,0,sizeof(minw));
    	for(i = 0 ; i <= maxn ; i++)
    		for(j = 0 ; j <= maxn ; j++)
    			G[i][j] = inf;
    	sumw = 0;
    }
    
    void prime(int n)
    {
    	int node,Minw;
    	for(i = 1 ; i <= n ; i++)
    		minw[i] = G[1][i];
    	//先把1结点放进最小生成树,那么要知道1到其余结点的最小权重
    	intree[1] = 1;//1点进入集合A,最小生成树集
    	for(i = 2 ; i <= n ; i++)
    	//一共n个点,已经把1加入最小生成树,那么还剩下n-1个点
    	{
    		Minw = inf;
    		for(j = 1 ; j <= n ; j++)
    		{
    			if(minw[j] < Minw && !intree[j])
    			{
    				Minw=minw[j];
    				node=j;
    			}
    		}
    		printf("选择的结点标号为:%d
    ",node);
    		intree[node]=1;
    		sumw+=Minw;
    		//每次在A中加入新的点,更新顶结点到各节点的权重
    		for(j=1;j<=n;j++)
    			if(!intree[j]&&minw[j]>G[node][j])
    			//更新B集合
    				minw[j]=G[node][j];
    	}
    }
    
    int main()
    {
        //freopen("Prim_in.txt", "r", stdin);
        //freopen("Prim_out.txt", "w", stdout);
    	int N,M,a,b,w;
    	while(cin>>N>>M,N,M)
        {
            init();
            for(i=1;i<=M;i++)
            {
                cin>>a>>b>>w;
                G[a][b]=w;
                G[b][a]=w;
            }
            prime(N);
            cout<<sumw<<endl;
        }
    	return 0;
    }
    /*测试数据
    4 5
    1 4 1
    1 2 6
    2 3 3
    2 4 4
    3 4 2
    6 9
    1 2 6
    1 3 1
    1 4 5
    2 3 5
    2 5 3
    3 4 5
    3 6 4
    4 6 2
    5 6 6
    0 0
    */

    3、数字三角形,题意随便模拟一下就好,既可以用暴力解决也可以用动态规划解决。

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    
    #define maxn 10000+5
    
    using namespace std;
    
    int D[maxn][maxn];
    int memon[maxn][maxn];
    
    int num;
    //menon数组记忆每一次计算后的值,避免重复计算,O(n^2)
    int MinSum(int i, int j)
    {
        if(memon[i][j] != -1)
            return memon[i][j];
        if(i == num)
            memon[i][j] = D[i][j];
        else{
            int x = MinSum(i + 1, j);
            int y = MinSum(i + 1, j + 1);
            memon[i][j] = min(x,y) + D[i][j];
        }
        return memon[i][j];
    }
    
    int main()
    {
        int i, j;
        while(cin >> num,num)
        {
            memset(memon,-1,sizeof(memon));
            for(i = 1; i <= num; i ++)
            for(j = 1; j <= i; j ++)
                cin >> D[i][j];
            cout << MinSum(1,1) << endl;
        }
        return 0;
    }

    4、求两个子序列的最长公共子序列的长度并且输出最长公共子序列。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    
    using namespace std;
    const int maxn = 1000 + 5;
    int n, m;
    long long a[maxn], b[maxn];
    int f[maxn][maxn];
    int pre[maxn][maxn];
    
    int main()
    {
        freopen("LCS_in.txt", "r", stdin);
        freopen("LCS_out.txt", "w", stdout);
    	int t,i,j;
    	cin>>t;
    	while(t--)
        {
    		cin>>n;
    		  for(i=1;i<=n;i++)
    		    scanf("%lld",a+i);
    		cin>>m;
    		  for(i=1;i<=m;i++)
                scanf("%lld",b+i);
    		memset(pre, -1, sizeof(pre));
    		memset(f, 0, sizeof(f));
    		for(i=1;i<=n;i++)
    		{
    			int v=0,k=0;
    			for(j=1;j<=m;j++)
    			{
    				f[i][j]=f[i-1][j];
    				if(a[i]>b[j]&&v<f[i-1][j])
                        v=f[i-1][j],k=j;
    				if(a[i]==b[j]&&v+1>f[i][j])
                        f[i][j]=v+1,pre[i][j]=k;
    			}
    		}
    		int k=1;
    		for(i=1;i<=m;i++)
    		if(f[n][i]>f[n][k])
                k=i;
    		cout<<f[n][k]<<endl;
    		if(f[n][k]==0) continue;
    		vector<int> ans;
    		for(i=n;i>=1;i--)
              if(pre[i][k]!=-1)
                ans.push_back(a[i]),k=pre[i][k];
    		      cout<<ans.back();
    		for(i=ans.size()-2;i>=0;i--)
              cout<<" "<<ans[i];
                cout<<endl<<endl;
    	}
    }

    5、两条线段是否相交。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    int main()
    {
        freopen("line_in.txt", "r", stdin);
        freopen("ine_out.txt", "w", stdout);
        double x1,x2,x3,x4,y1,y2,y3,y4,k1,k2;
        double w1,w2,w3,w4;
        while(cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4)
        {
           int flag=0;
           if((x2-x1)==0)              //如果斜率不存在
           {
              if((x3>=x2&&x4<=x2)||(x4>=x2&&x3<=x2))
                 flag+=1;
           }
            else                    //如果存在
            {
                k1=(y2-y1)/(x2-x1);
                w3=k1*(x3-x2)+y2;
                w4=k1*(x4-x2)+y2;
                if((y3>=w3&&y4<=w4)||(y3<=w3&&y4>=w4))      //看图模拟一遍
                    flag+=1;
            }
            if((x4-x3)==0)                  //继续判断斜率是否存在
            {
                if((x2>=x3&&x1<=x3)||(x1>=x3&&x2<=x3))
                    flag+=1;
            }
            else
            {
                k2=(y4-y3)/(x4-x3);
                w1=k2*(x1-x3)+y3;
                w2=k2*(x2-x3)+y3;
                if((y2>=w2&&y1<=w1)||(y2<=w2&&y1>=w1))
                    flag+=1;
            }
            if(flag==2)
                cout<<"yes"<<endl;
            else
                cout<<"no"<<endl;
        }
        return 0;
    }

    6、计算凸多边形面积。

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<iomanip>
    using namespace std;
    
    struct point
    {
        double x;
        double y;
    };
    
    point a[100];
    
    double area(point m,point n)
    {
        return (m.x*n.y - m.y*n.x)/2;
    }
    
    int main()
    {
        freopen("polygon_in.txt", "r", stdin);
        freopen("polygon_out.txt", "w", stdout);
        int n;
        while(cin>>n,n)
        {
            for(int i = 0;i<n;i++)
                cin>>a[i].x>>a[i].y;
            double sum = area(a[n-1],a[0]);
            for(int i = 1;i<n;i++)
            {
                sum+=area(a[i-1],a[i]);
            }
            cout<<fixed<<setprecision(2)<<sum<<endl;
        }
    }
  • 相关阅读:
    Python 面向对象编程
    snmp获取交换机端口和对应ip
    python IPy
    Django F()与Q()函数
    装饰器使用
    log日志信息查看
    shell简单入门
    gunicorn开启、关闭和重启
    CF1453B
    ACWing845 八数码(BFS,全排列hash)
  • 原文地址:https://www.cnblogs.com/darklights/p/7838271.html
Copyright © 2011-2022 走看看