首页 > 试题广场 >

魔法阵

[编程题]魔法阵
  • 热度指数:3872 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

小Q搜寻了整个魔法世界找到了四块魔法石所在地,当4块魔法石正好能构成一个正方形的时候将启动魔法阵,小Q就可以借此实现一个愿望。

现在给出四块魔法石所在的坐标,小Q想知道他是否能启动魔法阵


输入描述:
输入的第一行包括一个整数(1≤T≤5)表示一共有T组数据

每组数据的第一行包括四个整数x[i](0≤x[i]≤10000),即每块魔法石所在的横坐标

每组数据的第二行包括四个整数y[i](0≤y[i]≤10000),即每块魔法石所在的纵坐标


输出描述:
对于每组数据,如果能启动魔法阵输出“Yes”否则输出“No”。
示例1

输入

3
0022
0202
0156
1605
0077
0303

输出

Yes
Yes
No

一个小bug:这题输入没有用空格隔开 采用string输入 由于测试样例的数都在0-9之间 所以我这种输入方法没有出问题
解法:选用对角线相等且任意一组邻边相等这条判断准则判断是否是正方形
注意:输入的点不一定是按绕正方形一圈顺序的 可能是乱的 这是一个比较麻烦的点。考虑到这一点很多人的答案都不太准确。
步骤:
1.将4个点保存到数组x[] y[]
2.求每个点到剩下三个点的距离 如果是正方形 那么必须满足条件
    a.这三个距离中的最长的是对角线
    b.剩下两个长度必须相等
3.对每个点求出的对角线长度作比较,这些对角线长度必须相等。(由于点的顺序随机 至少要算3个对角线才能保证求的是不同的对角线)

#include <iostream>
#include <cmath>
#include <climits>
#include<string>
using namespace std;
int x[4], y[4];
int T;
int main(){
    cin>>T;
    while(T--){
        string s1, s2;  cin>>s1>>s2;
        for(int i = 0; i < 4; i++) {x[i] = s1[i] - '0';y[i] = s2[i] - '0';}
        bool flag = 1;
        int Cross = 0;
        for(int i = 0; i < 4; i++){
            int arr[3], cnt = 0, cross = 0, sum = 0;
            for(int j = 0; j < 3; j++){ //求某个点和剩下三个点距离  if(j == i) continue;
                arr[cnt++] = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);
                cross = max(cross, arr[cnt-1]);  //最长的为对角线
                sum += arr[cnt-1];
            }
            int val = (sum - cross) / 2;  //边长值
            for(int k = 0; k < 3 && arr[k] != cross; k++)
                flag &= (val == arr[k]);  //剩下两条边长要相等
            if(!Cross) Cross = cross; //保留第一个对角线的值
            else flag &= (Cross == cross);  //对角线必须相等
        }
        if(flag) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
}

编辑于 2019-05-25 11:28:50 回复(0)
我的判断条件是:
求出4个点之间各自的距离的平方为d1,d2,d3,d4,d5,d6,然后将他们从小到大排序,需要满足的条件是:
1. 前4个数字相等;2.后面两个数字相等;3.前两个相加等于最后一个数字。
python代码如下:
n=int(input())
for i in range(n):
    x=input()
    y=input()
    [p1,q1,r1,s1]=[int(x[0]),int(x[1]),int(x[2]),int(x[3])]
    [p2,q2,r2,s2]=[int(y[0]),int(y[1]),int(y[2]),int(y[3])]
    dd1=(r2-p2)*(r2-p2)+(r1-p1)*(r1-p1)
    dd2=(q2-p2)*(q2-p2)+(q1-p1)*(q1-p1)
    dd3=(s2-p2)*(s2-p2)+(s1-p1)*(s1-p1)
    dd4=(q2-r2)*(q2-r2)+(q1-r1)*(q1-r1)
    dd5=(q2-s2)*(q2-s2)+(q1-s1)*(q1-s1)
    dd6=(r2-s2)*(r2-s2)+(r1-s1)*(r1-s1)
    d=list([dd1,dd2,dd3,dd4,dd5,dd6])
    d.sort()
    if d[0]==d[1]==d[2]==d[3] and d[4]==d[5] and d[0]+d[1]==d[4]:
        print("Yes")
    else:
        print("No")
发表于 2020-04-24 00:02:11 回复(1)
#include <bits/stdc++.h>

using namespace std;

bool cmp(double a, double b) 
{     return a > b;
}

double dist(int x1, int y1, int x2, int y2)
{     return sqrt(pow(x1-x2,2)+pow(y1-y2,2));
}

int main()
{     int T;     cin>>T;     while(T--)     {         string x,y;         cin>>x>>y;         double d[6];         int k = 0;         for(int i=0;i<3;i++)             for(int j=i+1;j<4;j++)                 d[k++] = dist(x[i],y[i],x[j],y[j]);         sort(d,d+k,cmp);         if(d[0]==d[1] && d[2]==d[4])             puts("Yes");         else             puts("No");         return 0;
}

发表于 2019-01-25 01:58:50 回复(0)
不知道为啥你们都搞得那么复杂,这道题直接用两条对角线向量的模相等且数量积为0来判定即可,题目的测试数据应该是确保了是按照abcd点的顺序输入的,即a为起点,b和c为以a为向量起点的相邻两条边的终点,d为以a为起点的对角线向量的终点。

def solve(xs, ys):
    ad = [xs[3]-xs[0], ys[3]-ys[0]]
    bc = [xs[2]-xs[1], ys[2]-ys[1]]
    
    if (ad[0] ** 2 + ad[1] ** 2) == (bc[0] ** 2 + bc[1] ** 2) and (ad[0] * bc[0] + ad[1] * bc[1] == 0):
        return True
    return False

T = int(input())
for i in range(T):
    xs = [int(item) for item in list(input())]
    ys = [int(item) for item in list(input())]
    if solve(xs, ys) == True:
        print('Yes')
    else:
        print('No')
	


发表于 2021-09-08 19:00:51 回复(0)
判断方法:正方形的对角线相互垂直且长度相等,即两个对角线的斜率相乘等于-1,且欧氏距离的平方相等(用平方判断,避免计算欧氏距离时开方计算导致浮点数是否相等判断不准)。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine().trim());
        while(T-- > 0){
            char[] charX = br.readLine().trim().toCharArray();
            int[] x = new int[charX.length];
            for(int i = 0; i < x.length; i++) x[i] = charX[i] - '0';
            char[] charY = br.readLine().trim().toCharArray();
            int[] y = new int[charY.length];
            for(int i = 0; i < y.length; i++) y[i] = charY[i] - '0';
            if((y[2] - y[1])*(y[3] - y[0]) == -(x[2] - x[1])*(x[3] - x[0]) && 
                Math.pow(y[2] - y[1], 2) + Math.pow(x[2] - x[1], 2) == Math.pow(y[3] - y[0], 2) + Math.pow(x[3] - x[0], 2))
                System.out.println("Yes");
            else
                System.out.println("No");
        }
    }
}


编辑于 2021-02-06 00:29:02 回复(3)
只需要判断x的max-min差值和y的max-min差值是否相等即可,相当于补上四个三角形
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner scanner=new Scanner(System.in);
        int n=scanner.nextInt();
        String[] current;
        for(int i=0;i<n;i++){
            int maxX=-1,minX=10001;
            current=scanner.next().split("");
            for(int j=0;j<4;j++){
                maxX=Math.max(maxX,Integer.valueOf(current[j]));
                minX=Math.min(minX,Integer.valueOf(current[j]));
            }
            
            int maxY=-1,minY=10001;
            current=scanner.next().split("");
            for(int j=0;j<4;j++){
                maxY=Math.max(maxY,Integer.valueOf(current[j]));
                minY=Math.min(minY,Integer.valueOf(current[j]));
            }
            
            if(maxX-minX==maxY-minY){
                System.out.println("Yes");
            }else{
                System.out.println("No");
            }
        }
        
    }
}

发表于 2020-06-23 15:15:24 回复(1)
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t,a[10000],m=0,x[4],y[4];
    cin>>t;
    for(int i=0;i<t;i++)
    {
        cin>>x[0]>>x[1]>>x[2]>>x[3];
        cin>>y[0]>>y[1]>>x[2]>>x[3];
        int k1,k2,t1,t2,t3,t4;
        k1=(y[0]-y[2])/(x[0]-x[2]);
        k2=(y[1]-y[3])/(x[1]-x[3]);
        t1=sqrt(pow(x[0]-x[2],2)+pow(y[0]-y[2],2));
        t2=sqrt(pow(x[1]-x[3],2)+pow(y[1]-y[3],2));
        t3=sqrt(pow(x[0]-x[1],2)+pow(y[0]-y[1],2));
        t4=sqrt(pow(x[2]-x[3],2)+pow(y[2]-y[3],2));
        if(k1==k2&&t1==t2&&t2==t3&&t3==t4)
        {
            a[m]=1;
            m++;
        }
        else
        {
            a[m]=0;
            m++;
        }
    }
    for(int k=0;k<m;k++)
    {
        if(a[k]==1)
          cout<<"Yes"<<endl;
        else
          cout<<"No"<<endl;
    }
    return 0;
}

发表于 2019-06-27 11:05:00 回复(0)
//求出每对顶点之间距离的平方,只有两种情况,边长和对角线
//只要出现第三种结果就是错的
#include<bits/stdc++.h>
using namespace std;
int num;
vector<int>x(4);
vector<int>y(4);
bool judge(vector<int>&x,vector<int>&y){
    int w=0;
    for(int i=0;i<3;i++){
        for(int j=i+1;j<4;j++){
            int k=pow(x[i]-x[j],2)+pow(y[i]-y[j],2);
            if(w==0) w=k;
            else if(k!=w&&k!=2*w&&k!=w/2) return false;
        }
    }
    return true;
}
int main(){
    scanf("%d",&num);
    string m,n;
    for(int i=0;i<num;++i){
        cin>>m>>n;
        for(int j=0;j<4;j++)
            x[j]=m[j]-'0';
        for(int j=0;j<4;++j)
           y[j]=n[j]-'0';
        if(judge(x,y)) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
    return 0;
}

发表于 2022-09-14 22:48:09 回复(0)
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int t=in.nextInt();
        while(t>0){
            int[] rows=new int[4];
            int idx=0;
            String s=in.next();
            for(int i=0;i<s.length();i++){
                rows[idx++]=(int)(s.charAt(i)-'0');
            }
            int[] cols=new int[4];
            s=in.next();
            idx=0;
            for(int i=0;i<s.length();i++){
                cols[idx++]=(int)(s.charAt(i)-'0');
            }
            Map<Integer,Integer> cnt=new HashMap();
            int max=0;
            for(int i=0;i<4;i++){
                for(int j=i+1;j<4;j++){
                    int distance=(rows[i]-rows[j])*(rows[i]-rows[j])+(cols[i]-cols[j])*(cols[i]-cols[j]);
                    cnt.put(distance,cnt.getOrDefault(distance,0)+1);
                    if(cnt.get(distance)>max) max=cnt.get(distance);
                }
            }
            System.out.println(cnt.size()==2&&max==4?"Yes":"No");
            t--;
        }
    }
}

发表于 2023-09-05 22:54:37 回复(0)
while(true){
    $n=0;
    fscanf(STDIN, "%d", $n);
    
    if(empty($n)){
        exit;
    }

    for($j=0; $j<$n; $j++){
        // 使用%s取值,不然0会***掉
        fscanf(STDIN, "%s", $x); // x轴
        fscanf(STDIN, "%s", $y); // y轴
       
        $xx = str_split($x);
        $yy = str_split($y);

        $arr = []; // 保存各点之间的距离
        for($i=0; $i<4; $i++){
            for($ii=0; $ii<4; $ii++){
                if($ii==$i){
                    continue;
                }
                $arr[] = abs(pow($xx[$i]-$xx[$ii], 2)+pow($yy[$i]-$yy[$ii], 2));
            }
        }
     
        // 4位 8位
        $return = [];
        foreach($arr as $key=>$val){
            $return[$val]++;
        }
        
        if(count($return) != 2){
            echo "No\n";
        }else{
            echo "Yes\n";
        }
    }
}

发表于 2022-05-28 19:37:25 回复(0)
import sys
T = sys.stdin.readline()
T = int(T.strip())
for _ in range(T):
    xs = sys.stdin.readline()
    ys = sys.stdin.readline()
    xs = xs.strip()
    ys = ys.strip()
    x = list(map(int,xs))
    y = list(map(int,ys))
    t = [(x[i],y[i]) for i in range(4)]
    t.sort()
    x01 = t[1][0] - t[0][0]
    x23 = t[3][0] - t[2][0]
    x02 = t[2][0] - t[0][0]
    y01 = t[0][1] - t[1][1]
    y13 = t[1][1] - t[3][1]
    y02 = t[0][1] - t[2][1]
#     print(t)
    if x01 == x23 and y13 == y02 and (x02 == y01 or x02 + y01 == 0):
        print("Yes")
    else:
        print("No")
发表于 2022-04-22 07:49:15 回复(0)
#计算两点距离
def dis(a,b):
    x=a[0]-b[0]
    y=a[1]-b[1]
    d=(x**2+y**2)**(1/2)
    return d

t=int(input())
for _ in range(t):
    x=list(input())
    y=list(input())
    li=[]
    #用li存放四个坐标[[,],[,],[,],[,]]
    for i in range(4):
        li.append([int(x[i]),int(y[i])])
    ds=[]
    #用ds存放六个距离[,,,,,]
    for i in range(3):
        for j in range(4):
            if i<j:
                ds.append(dis(li[i], li[j]))
    #距离排序,前四个距离应该相等,后两个距离也应该相等且等于前四个的根号2倍
    ds=sorted(ds)
    if  ds[4]==ds[5] and ds[4]/ds[3]==2**(1/2) and ds[3]==ds[2] and ds[2]==ds[1] and ds[1]==ds[0]:
        print("YES")
    else:
        print("No")
发表于 2022-03-04 11:11:32 回复(0)
//计算每一个边长长度,用map储存边长长度及其数量。如果边长长度只有两种而且是4边长同长加余下2边长同长,就是正方形。否则不是。
#include<iostream>
#include<vector>
#include<map>
#include<cmath>

using namespace std;

void print(bool find){
    if(find){
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
}

int main()
{
    vector<vector<int>> data;
    map<double, int> lengthdata;
    vector<int> temp;
    int T, x;
    cin >> T;
    for(int i = 0; i < T; i++){
        string s;
        data.push_back(temp);
        data.push_back(temp);
        cin >> s;
        for(int i = 0; i < 4; i++){
            x = s[i] - '0';
            data[0].push_back(x);
        }
        cin >> s;
        for(int i = 0; i < 4; i++){
            x = s[i] - '0';
            data[1].push_back(x);
        }
        for(int i = 0; i < 3; i++){
            for(int j = i + 1; j < 4; j++){
                double l = sqrt(pow(abs(data[0][i] - data[0][j]), 2) + pow(abs(data[1][i] - data[1][j]), 2));
                if(lengthdata.empty() || lengthdata.find(l) == lengthdata.end()){
                    lengthdata.insert(std::pair<double, int>(l, 1));
                } else {
                    lengthdata.find(l)->second += 1;
                }
            }
        }
        int size = 0;
        for(auto it = lengthdata.begin(); it != lengthdata.end(); it++){
            size++;
        }
        if(size != 2){
            print(false);
        } else {
            if(lengthdata.begin()->second == 2 || lengthdata.begin()->second == 4){
                print(true);
            } else {
                print(false);
            }
        }
        data.clear();
        lengthdata.clear();
    }
    return 0;
}
发表于 2021-10-02 22:05:04 回复(0)
while True:
    try:
        T = int(raw_input())
        for i in range(T):
            x = list(map(int, raw_input()))
            y = list(map(int, raw_input()))
            if sorted(x) == sorted(y):
                print("Yes")
            else:
                print("No")
    except:
        break

发表于 2021-09-20 15:15:00 回复(0)
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
int main()
{
    int T,x,y;
    while(std::cin>>T)
    {
        std::string s,t;
        for(int i=0;i<T;i++)
        {
            std::vector<int>x;
            std::vector<int>y;
            std::cin>>s>>t;
            for(int j=0;j<4;j++)x.push_back(s[j]);
            for(int j=0;j<4;j++)y.push_back(t[j]);
            int d1=(x[0]-x[1])*(x[0]-x[1])+(y[0]-y[1])*(y[0]-y[1]);
            int d2=(x[0]-x[2])*(x[0]-x[2])+(y[0]-y[2])*(y[0]-y[2]);
            int d3=(x[0]-x[3])*(x[0]-x[3])+(y[0]-y[3])*(y[0]-y[3]);
            int d4=(x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2]);
            int d5=(x[1]-x[3])*(x[1]-x[3])+(y[1]-y[3])*(y[1]-y[3]);
            int d6=(x[2]-x[3])*(x[2]-x[3])+(y[2]-y[3])*(y[2]-y[3]);
            int b[6]={d1,d2,d3,d4,d5,d6};
            std::sort(b,b+6);
            if(b[0]==b[1]&&b[1]==b[2]&&b[2]==b[3]&&b[0]*2==b[4])std::cout<<"Yes"<<std::endl;
            else std::cout<<"No"<<std::endl;
            
        }
    }
    return 0;
}
发表于 2020-09-13 17:57:19 回复(0)
求出点之间的距离,按顺序求四条线(边或对角线),如果四条线都相等,说明是菱形或正方形,再求对角线的平方是否为边长的平方的两倍。如果四条线不相等,求所有线之和是否为边长的平方的六倍。
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
struct pos {
	int x;
	int y;
};

int distance(pos p1, pos p2) {
	return pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2);
}

string magic(vector<pos> p) {
	int d1 = distance(p[0], p[1]);
	int d2 = distance(p[2], p[1]);
	int d3 = distance(p[2], p[3]);
	int d4 = distance(p[0], p[3]);
	int total = 0;
	if (d1 == d2 && d2 == d3 && d3 == d4) {
		int cross = distance(p[0], p[2]);
		if (cross = 2 * d1)
			return "Yes";
		else return "No";
	}
	else if (d1 + d2 + d3 + d4 == pow(min(d1, d2), 2) * 6) return "Yes";
	return "No";
}

int main() {
	vector<pos> p(4);
	int n; cin >> n;
	for (int i = 0; i < n; i++) {
		string x; cin >> x;
		string y; cin >> y;
		for (int j = 0; j < 4; j++)
			p[j].x = x[j] - '0';
		for (int j = 0; j < 4; j++)
			p[j].y = y[j] - '0';
		cout << magic(p) << endl;
	}
}


发表于 2020-09-08 11:53:45 回复(0)
import sys
group_num = None
group = []
temp = []

for line in sys.stdin:
    if group_num is None:
        group_num = int(line.strip('\n'))
    else:
        temp.append(list(map(int,list(line.strip('\n')))))
        if len(temp)==2:
            group = (list(zip(temp[0],temp[1])))
            d = []
            for i in range(1,len(group)):
                d0 = pow(group[i][0]-group[0][0],2)+pow(group[i][1]-group[0][1],2)
                if not d0 in d:
                    d.append(d0)
            if not len(d) == 2:
                print('No')
            elif not max(d) == 2*min(d):
                print('No')
            else:
                print('Yes')
            temp = []

发表于 2020-09-06 17:11:01 回复(0)
对于正方形,其每一个点与其他三个点的距离关系必是两个相同的直角边加一条对角线。全部四个点
加起来记录就是8个同样长度的直角边与4个同样长度的对角线。
import math

def distance(cod1, cod2):
    x1, x2 = int(cod1[0]), int(cod2[0])
    y1, y2 = int(cod1[1]), int(cod2[1])
    d = math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
    return d

while True:
    try:
        n = int(input())
        for i in range(0, n):
            x_T = input()
            y_T = input()
            
            cods = []
            for i in range(0, 4):
                cods.append(x_T[i] + y_T[i])
            
            dic = dict()
            for cod in cods:
                for i in range(0, 4):
                    d = distance(cod,cods[i])
                    if(d == 0):
                        # do nothing
                        pass
                    elif(d not in dic):
                        dic[d] = 1
                    else:
                        dic[d] += 1
            
            if(len(dic) == 2 and sum(dic.values()) == 12):
                print("Yes")
            else:
                print("No")
    except:
        break



发表于 2020-08-22 21:12:54 回复(0)
from collections import Counter

for i in range(int(input())):
    x, y = list(map(int, input())), list(map(int, input()))
    d = Counter([(x[i] - x[j]) ** 2 + (y[i] - y[j]) ** 2 for i in range(3) for j in range(i + 1, 4)])
    a, b = min(d), max(d)
    print("Yes" if len(d) == 2 and b == 2 * a and d[a] == 4 and d[b] == 2 else "No")

编辑于 2020-07-13 23:18:10 回复(0)
先找垂直的对角线,再判断两边是否平行。
#include<bits/stdc++.h>
using namespace std;

bool is_parallel(int x[], int y[], int a1, int a2, int a3, int a4){
    return (((x[a1]-x[a2])==(x[a3]-x[a4]))&&((y[a1]-y[a2])==(y[a3]-y[a4])))||(((x[a1]-x[a2])==-(x[a3]-x[a4]))&&((y[a1]-y[a2])==-(y[a3]-y[a4])));
}

bool is_vertical(int x[], int y[], int a1, int a2, int a3, int a4){
    return !((x[a1] - x[a2])*(x[a3] - x[a4]) + (y[a1] - y[a2])*(y[a3] - y[a4]));
}
int main(){
    int t;
    cin>>t;
    for(int i =0;i<t;i++){
        int x[5], y[5];
        for(int j=0;j<4;j++) {
            char c;
            cin>>c;
            x[j] = c-'0';
        }
        for(int j=0;j<4;j++) {
            char c;
            cin>>c;
            y[j] = c-'0';
        }
        
        if(is_vertical(x, y, 0, 1, 2, 3)&&is_parallel(x, y, 0, 2, 3, 1)){
            cout<<"Yes"<<endl;
        }else if (is_vertical(x, y, 0, 2, 1, 3)&&is_parallel(x, y, 0, 1, 2, 3)){
            cout<<"Yes"<<endl;
        }else if (is_vertical(x, y, 0, 3, 1, 2)&&is_parallel(x, y, 0, 1, 2, 3)){
            cout<<"Yes"<<endl;
        }else cout<<"No"<<endl;
    }
    return 0;
}
发表于 2020-07-03 00:59:20 回复(0)

问题信息

上传者:小小
难度:
32条回答 5223浏览

热门推荐

通过挑战的用户

查看代码