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;
        }
    }
  • 相关阅读:
    MSDN Magazine搞错了
    Visual Studio 2005中设置调试符号(Debug Symbols)
    BCB 6的问题
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现人与身份证的一对一关系映射
    吴裕雄天生自然Spring BootSpring Data JPA
    吴裕雄天生自然Spring BootSpring Boot对JSP的支持
    吴裕雄天生自然Spring BootSpring Boot的异常统一处理
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现Author与Article的一对多关系映射
    吴裕雄天生自然Spring Boot解决 Error creating bean with name 'entityManagerFactory' defined in class path resource
    吴裕雄天生自然Spring Boot@ExceptionHandler注解和@ControllerAdvice注解
  • 原文地址:https://www.cnblogs.com/darklights/p/7838271.html
Copyright © 2011-2022 走看看