非精写版-51nod基础训练

Posted iuk11

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了非精写版-51nod基础训练相关的知识,希望对你有一定的参考价值。

四点共面

已知四个点,判断是否共面。可以求出三条向量,利用向量积求立方体体积,若体积是0,则四点共面。
求出的三个向量: d 1 = ( x 1 , y 1 , z 1 ) d_1=(x_1,y_1,z_1) d1=(x1,y1,z1) d 2 = ( x 2 , y 2 , z 2 ) d_2=(x_2,y_2,z_2) d2=(x2,y2,z2) d 3 = ( x 3 , y 3 , z 3 ) d_3=(x_3,y_3,z_3) d3=(x3,y3,z3) V = d 1 ∗ d 2 ∗ d 3 V=d_1*d_2*d_3 V=d1d2d3 V = ( x 1 y 2 z 3 + x 2 y 3 z 1 + x 3 y 1 z 2 ) − ( x 1 y 3 z 2 + x 2 y 1 z 3 + x 3 y 2 z 1 ) V=(x_1y_2z_3+x_2y_3z_1+x_3y_1z_2)-(x_1y_3z_2+x_2y_1z_3+x_3y_2z_1) V=(x1y2z3+x2y3z1+x3y1z2)(x1y3z2+x2y1z3+x3y2z1)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node{
    int x,y,z;
}e[5],d[5];
int main(){
    int t;
    cin>>t;
    while(t--){
        for(int i=0;i<4;i++){
            cin>>e[i].x>>e[i].y>>e[i].z;
            if(i){
                d[i].x=e[i-1].x-e[i].x;
                d[i].y=e[i-1].y-e[i].y;
                d[i].z=e[i-1].z-e[i].z;
            }
        }
        ll d1=d[1].x*d[2].z*d[3].y+d[1].y*d[2].x*d[3].z+d[1].z*d[2].y*d[3].x;
        ll d2=d[1].x*d[2].y*d[3].z+d[2].x*d[3].y*d[1].z+d[3].x*d[1].y*d[2].z;
        if(d1==d2){
            cout<<"Yes\\n";
        }else{
            cout<<"No\\n";
        }
    }
    //system("pause");
    return 0;
}

好像是因为贴代码的改版了,之前屯的发不了了。


线段相交

线段相交,是给出两两顶点,确定一条线段,判断两线段是否相交。
重点就在于判断线段是否相交,之前的数学思想是两直线是否相交,那么联立方程组,如果不平行,就一定相交。但线段的交点判断可不仅仅是对平行的判断。(之前的圆与三角形题目中也有求线段是否相交的要求)。


走迷宫

数据范围很小,只需要回溯记录每条路径即可。

#include<bits/stdc++.h>
using namespace std;
int dir[4][2]={
    {1,0},{-1,0},{0,1},{0,-1}
};
int maps[10][10];
int vis[10][10];
int n,m,t;
int sx,sy;
int fx,fy;
int ans=0;
bool check(int x,int y){
    if(x>n||y>m||x<1||y<1||maps[x][y]) return false;
    return true;
}
void dfs(int x,int y){
    if(x==fx&&y==fy){
        ans++;
    }
        for(int i=0;i<4;i++){
            int xx=x+dir[i][0];
            int yy=y+dir[i][1];
            if(!vis[xx][yy]&&check(xx,yy)){
                vis[xx][yy]=1;
                dfs(xx,yy);
                vis[xx][yy]=0;
            }
        }
    
}
int main(){
    cin>>n>>m>>t;
    cin>>sx>>sy>>fx>>fy;
    while(t--){
        int x,y;
        cin>>x>>y;
        maps[x][y]=1;
    }
    vis[sx][sy]=1;
    dfs(sx,sy);
    cout<<ans<<endl;
    //system("pause");
    return 0;
}

迷宫游戏

之前(最短路径)那道题的dijkstra的板子。
用优先队列优化,优先队列用的好,dijkstra的时间复杂度就低。
在网上还找到了一份结构体的,但是结构体的重载很麻烦,不同的编译器可能会报错。用<pair>很方便。
思路就是我们只需要去寻找最短路就好,在路径传递的过程中把选中的点的权值加进去。如果有多条最短路,即有两个点间的两条路径的边权相同,就去比较一下谁的点权大,谁大就加谁的点权。最后维护出来到终点的mon[]数组,记录的就是最短路径下的最大点权。

#include<bits/stdc++.h>
using namespace std; 
const int maxn=505;
const int INF=0x3f3f3f3f;
int n,m,s,t;
int d[maxn];
int val[maxn];
int mon[maxn];
vector<pair<int,int> >E[maxn];
void init(){
    for(int i=0;i<maxn;i++) d[i]=INF;
    for(int i=0;i<maxn;i++) E[i].clear();
}
void dijkstra(int x){
	d[x]=0;
    mon[x]=val[x];
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >Q;
    Q.push(make_pair(d[x],x));            //优先队列自动根据pair中的first从大到小排序(默认), 放入 负距离,则 边短的先弹出
    while(!Q.empty()){
        int now=Q.top().second;            //显然,now 为一个起点
        Q.pop();
        if(now==t) break;
        for(int j=0;j<E[now].size();j++){
            int v=E[now][j].first;         //显然,v 为 now 可以到达的一个终点
            if(d[v]>d[now]+E[now][j].second){    //如果 已知的v 到 s 的距离 大于 now这个点到 s 的距离 + now 这个点到 v 的距离, 更新一下, 并放入优先队列
                d[v]=d[now]+E[now][j].second;
                mon[v]=val[v]+mon[now];
                Q.push(make_pair(d[v],v));
            }else if(d[v]==d[now]+E[now][j].second){
                if(mon[v]<val[v]+mon[now]){
                    mon[v]=val[v]+mon[now];
                    Q.push(make_pair(v,d[v]));
                }
            }
        }
    }
    return;
}
int main(){
	cin>>n>>m>>s>>t;
	s++;t++;
	init();
	for(int i=1;i<=n;i++) cin>>val[i];
    int u,v,w;
	for非精写版-51nod基础训练

非精写版-51nod基础训练

非精写版-51nod基础训练(终)

非精写版-51nod基础训练(持续更新)

51nod_1459 最短路 dijkstra 特调参数

1057 N的阶乘(51NOD基础题)