ARC001

ARC001

Aセンター採点

  • 题意:
  • 题解:
  • 代码:

Bリモコン

  • 题意:
  • 题解:
  • 代码

Cパズルのお手伝い

  • 题意:给定 (8 imes 8)的矩阵,让你求是否有八皇后问题放置解,如果有,则输出任意一个解。
  • 题解:就很普通的八皇后问题,dfs回溯寻找,如果有解直接输出然后退出程序,若跑完还没退出,则无解。关键点在于如何dfs,就很普通的坐标移动dfs,用(x)(y)移动回溯,判断则用标记数组,(r[i])表示第几行有,(c[i])表示第几列有,但是斜线较难不过仔细想想也能表示。
  • 代码:
#include <iostream>
#include <map>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const ll N = 1e3+9;
struct node {
    int w, v;
}a[N];
int dp[N][N];
char change[1010];
char ma[N][N];
int row[N];
int col[N];
int l[N];
int r[N];
int L(int i, int j) {
    return i + 8 - j;
}
int R(int i, int j) {
    return i + j - 1;
}
bool ff = 1;
int n = 8, m = 8;
void dfs(int x, int y) {
    if (y > m)y = 1, x++;
    if (x > n) {
        int cnt = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (ma[i][j] == 'Q')cnt++;
            }
        }
        if (cnt == 8) {
            for (int i = 1; i <= n; i++) {
                cout << (ma[i] +1) <<endl;
            }
            exit(0);
        }
        return;
    }
    if (!r[R(x, y)] && !l[L(x, y)] && !row[x] && !col[y] && ma[x][y] == '.') {
        r[R(x, y)] = 1;
        l[L(x, y)] = 1;
        row[x] = 1;
        col[y] = 1;
        ma[x][y] = 'Q';
        dfs(x, y + 1);
        ma[x][y] = '.';
        r[R(x, y)] = 0;
        l[L(x, y)] = 0;
        row[x] = 0;
        col[y] = 0;
    }
     dfs(x, y+1);
}
void solve() {
    for (int i = 1; i <= n; i++) {
        cin >> (ma[i] + 1);
    }
    ff = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 1;  j <=m; j++) {
            if (ma[i][j] == 'Q') {
                if (r[R(i, j)])ff = 0;
                if (l[L(i, j)])ff = 0;
                if (row[i])ff = 0;
                if (col[j])ff = 0;
                col[j] = 1;
                row[i] = 1;
                l[L(i, j)] = 1;
                r[R(i, j)] = 1;
            }
        }
    }
    if (ff) {
         dfs(1, 1);
    } 
        cout <<"No Answer
";
}
int main() {
    int t = 1;
    while (t--) {
         solve();
    }
}

Dレースゲーム

  • 题意:在网格图中给出起点和终点,求从起点到终点最短的距离,限制是这个类似跑道,给出(2n)个点,然后要从第(0)层跑到第(n)层,每次给两个点,只能在两点之间跑。
  • 题解:以起点为起始点,然后维护两条线段(l)(r),这两条线段是以起点为起始点,然后(l)(r)的终点分别是能以直线到达跑道端点的最左端点和最右端点,即想象把(l)(r)一直往两边倾斜碰到一点即停。然后,一层层得往下找,如果到了一层,两条线交叉了,说明要么到达的这一层,右边的端点在当前原点的(l)线的左侧,很显然如果在左侧,必然是让当前原点加上(l)改变当前原点的位置是最优的,如果你往中间走或者走(r)都是多走路,如果走弯曲的更是迷惑行为;要么到达的层左边的端点在当前原点的(r)线的右侧,同理让当前原点加上线段(r),答案即是每次更新时所加的线段的长度,最后改变终点坐标限制,左右端点都改成((ex, n + 1)),因为最后只能向着终点走,端点即无用。并且上述遍历结束,当前点一定是直接可以和终点相连,所以直接加上长度即可。
  • 代码:
#include <iostream>
#include <cmath>

using namespace std;
typedef long long ll;
const int N = 3e5 + 99;

struct Vector {
	double x, y;
	Vector (int xx, int yy) : x(xx), y (yy) {}
	Vector(){}//  
	double operator * (Vector rhs)const {//叉乘比较方便 
		return x * rhs.y-y * rhs.x;
	}
	Vector operator + (Vector rhs)const {
		return Vector(x + rhs.x, y + rhs.y);
	}
	Vector operator - (Vector rhs)const {
		return Vector(x - rhs.x, y - rhs.y);
	}
	double d() {
		return sqrt ( x * x + y * y);
	}
	void pr() {
		cout << x << " " << y << endl;
	}
}l[N], r[N];
int main() {
	int n;
	cin >> n;
	int sx, ex;
	cin >> sx  >> ex;
	for (int i = 0; i <= n; i++) {
		cin >> l[i].x >> r[i].x;
		l[i].y = 1.0 * i;
		r[i].y = 1.0 * i;
	}
	l[n].x = r[n].x = ex;//终点的要改一下 
	int i ,j = 0;
	Vector cur(sx, 0), li, ri;
	double ans= 0;
	while (j  + 1 <= n) {
		j = cur.y + 1;
		i = j + 1;
		li = l[j] - cur;//所要维护的l线 和r线 
		ri = r[j] - cur;
		while (j + 1<= n) {
			bool changeL = 0;
			if (li * (l[i] - cur) < 0)li = l[i] - cur, changeL = 1;//叉乘是右手握在纸面上是正 
			if (ri * (r[i] - cur) > 0)ri = r[i] - cur;//l线和r线向两边撕扯的过程 
			if (li * ri > 0) {//判断方向有没有出问题 
				if (changeL) {
					ans += ri.d();
					cur = cur + ri;
				} else {
					ans += li.d();
					cur = cur + li;
				}
				break;
			}
			j++;
			i++;
		}
	}	
	ans += (cur - l[n]).d();//最后加上答案 
	printf("%.15lf
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/Xiao-yan/p/14314623.html