프로그램 설계 생각 Week4-CSP 시뮬레이션 게임

프로그램 설계 생각 Week4-CSP 시뮬레이션 게임

A- 뻐꾸기 동쪽 모험

기술

반지에 대한 포인터, 문자 A의 첫 번째 점. 뻐꾸기 이스트 각 캔 회전 시계 방향 또는 반 시계 방향으로 한 칸. 예를 들어, z까지 시계 방향 회전은 반 시계 방향 회전 (B)에. 문자열의 뻐꾸기 이스트 손,하지만 그는 당신의 도움을 물어왔다, 그래서 차례의 최소 필요로 얼마나 많은 시간을 물어, 바보입니다.
문자열 입력 라인 번호 적어도 출력 우회전.

그림 삽입 설명 여기

견본

input:
zeus

output:
18

생각

먼저 각 문자에 대한 문자로 시작하는 문자에서 시계 방향 또는 반 시계 방향으로 회전하는 두 가지 옵션이있다 회전 수하는 처음부터있는 문자열의 길이를 계산하고 편지의 방법에 도달하는 최단 경로를 선택하고 초기 편지의 다음 회전은 그에 따라 업데이트되었습니다. 마지막으로, 셀의 누적 수 차례 최소 얻었다.

요약

이 질문은 주로 초기 편지를 업데이트 기억하고 싶은 회전 시계 방향과 반 시계 방향으로 다음마다로 세포의 수를 측정하기 위해, 비교적 간단

코드

#include <iostream>
#include <string>
#include <cmath>
#include<cstdlib>
#include<cstdio>
using namespace std;

int main()
{
	cin.sync_with_stdio(false);
	string str;
	cin >> str;
	int size = str.length();
	int sum = 0;
	char now = 'a';
	for (int i = 0; i < size; i++) {
		int left = abs(str[i] - now);
		int right = 26-left;
		sum += left < right ? left : right;
		now = str[i];
	}
	printf("%d\n", sum);
}


B- 뻐꾸기 이스트 먹고 싶어

기술

뻐꾸기 이스트는 매일 튀김 살 필요가 인공 지능. ① 한 번 구입이 튀김 일일 : 그러나 소비를 자극하기 위해 상점 튀김, 구입하는 두 가지 방법이 있습니다. ② 튀긴 오늘을 구입하지만, 내일이 튀긴 구입하기, 가게 티켓을의 올 다음날 수집 티켓을 제공 할 것입니다. 구입의 아니 나머지는이 두 가지 방법의 구입 여러 번 사용할 수 있지만, 뻐꾸기 동쪽은 검소 소년, 그는 훈련의 끝을 왼쪽, 티켓의 손은 훈련의 끝에서 허용되지 않습니다. 뻐꾸기 이스트 아주 부자가 돈 동쪽 뻐꾸기에 대해 걱정할 필요가 없습니다, 뻐꾸기 동쪽하지만, 바보, 그는 단지 그가 인공 지능 튀김 일 시험 일주일에 살 수 있는지 물어 싶었어요.
테스트 입력 주중 N (1 <= N <= 100,000), 및 수 N 매일 올리는 일이 인공 지능 구매 (0 <= <= 인공 지능 10000).

견본

input:
4
1 2 1 2

output:
YES

input:
3
1 0 1

output:
NO

생각

매일 때문에 당신은 언젠가는 축적 된 기록과 티켓 전에 티켓은 전날의 수는 티켓을 축적 발표 수는 실패한 구매에서 온 어느 날 살 때, 그래서 티켓은 밖으로 실행 축적해야한다 다음날 그렇지 않으면 공제를 두 번째 옵션을 선택하면 전날의 티켓 두 번째 옵션은 단지를 구입할 필요가 없습니다 튀김이나 볶음 살 필요까지 후. 사이클 후 티켓이 마지막 날의 끝에서 삭제할지 여부를 결정합니다.

요약

:이 질문은 몇 주에있다, 사실 어려운 일이 아니다
- <= 100000, 신중하게 제목을 읽어 변수 범위에주의 ① 1 <= n 개의이.
② 시작은, I는 상기 제 용액과 제 2 용액은 많은 경우에 0 회 이상, 결과를 채용 할 수있는, 데드 엔드 재귀 빠졌다. 사실, 대부분의 단지 두 번째 옵션에서 두 번째 옵션을 사용하여 상황에 관계없이 여러 번 하루는 간단한 많은, 만 0 또는 1의 값 티켓, 그래서 첫 번째 옵션에 대한 대안으로 사용할 수 있습니다.

코드

#include <iostream>
#include<cstdlib>
#include<cstdio>
using namespace std;

int a[100000];
int n;
bool flag = true;

int main()
{
	cin.sync_with_stdio(false);
	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> a[i];
	int ticket = 0;
	for (int i = 0; i < n; i++)
	{
		if (a[i] - ticket < 0) { flag = false; break; }
		ticket = (a[i] - ticket) % 2;

	}
	if (ticket != 0)flag = false;
	if (flag)cout << "YES";
	else cout << "NO";


}


C- 끔찍한 우주선

기술

무한 2 차원 평면에서의 우주선 전파 (도 2 차원 격자로 볼 수있다)를, 디폴트의 초기 상 방향. 우주선이 방향의 거리를 분할 한 후 방출되는
동일의 전원 상태, 우주선의 두 방향이 45 ° 분할 약! 우주선마다 분할 단위 길이를 분할하는 방향으로 진행한다 AI, N 회 분할한다.
위치의 총 수는 "대 지혜 다운"것이다 계산
= <(AI 분리 입력 우주선의 수 N (N <= 30), 및 우주선의 i 번째의 분할 인공 지능 원래 방향 길이 가서 계속 5).

그림 삽입 설명 여기

견본

input:
4
4 2 2 3

output:
39

생각

이 미로의 변형입니다, 당신은 DFS 나 BFS가 해결 사용할 수 있습니다. 이 강자 위치의 총 수는 우리가 각 위치 컬렉션 번만 표시되도록 설정 데이터 구조를 사용 칠레 대해 다운 계산할 필요하므로 광선 여러 위치가 중첩 될 n 번째 분할 존재한다. 이동 방향의 분할 선 어쨌든 옆으로 갈 수있는 상황 8 종류, 스토리지 배열의 움직임과 상황이있다.
우리는 재귀 DFS 앞으로 각 부문 스플릿 두 가시 광선 대신에 0 또는 4 DIR 같음 y 축에 대해 대칭 파라미터 DIR 축 방향에 따라 결정되며, 최종 경로에서 마지막 분할 분할 검색 사용 때 Y 대칭 = X 직선 대신 1 내지 5 DIR 동일 할 때 직선 (Y) 대신에 3 내지 7 DIR 같음 -x 대칭 = X 축, 상기 제 대칭 약 2 내지 6 주제 대칭으로 DIR 같 모든 가능한 위치는 마지막 집합이되도록, 포워드 푸시 된 경로, 대칭축과 상기 공지의 대칭 선을 세트 포인트를 추가 광선의 특성에 좌우 대칭의 다른 점을 유추 할 수있는 수직 이등분선 사이에 첨가되고 크기 위치의 수는 지적인 전투 감소한다.

요약

이것은 전형적인 미로의 변형이고, 키는 이동 방향은 일반적으로 어렵고, 8을 포함하는 것을 제외하고 그 채널 미로 전에 중복 즉, 분할 위치의 경로 메모리이다.
처음에 나는 BFS 문제 해결을 사용하려고하지만 몇 시간이 초과되거나 치기 후 :

int bfs() {
	Q.push(point(0,0,0));
	while (!Q.empty()) {
		point now = Q.front();
		Q.pop();
		point temp;
		for (int i = 1; i <= a[index]; i++)
		{
			//cout << now.x + dx[now.dir] * i << " " << now.y + dy[now.dir] * i << endl;
			P.push_back(point2(now.x + dx[now.dir] * i, now.y + dy[now.dir] * i));
		}

		temp.x = now.x + dx[now.dir] * a[index];
		temp.y = now.y + dy[now.dir] * a[index];
		temp.dir = now.dir;
		

		sort(P.begin(), P.end(), cmp);

		int u = 0, v = 1;
		while (v < P.size()) {
			if (P[u] == P[v]) {  P.erase(P.begin() + v); }
			else { u = v; v = u + 1; }
		}
		if (index == 0)index++;
		else { 
			k++;
			if (pow(2, index+1) == k)index++;
		}
		
		if (index == n)return P.size();

		int d1 = temp.dir+1;
		int d2 = temp.dir - 1;
		if (d1 == 8)d1 = 0;
		if (d2 == -1)d2 = 7;
		Q.push(point(temp.x, temp.y, d1));
		Q.push(point(temp.x, temp.y, d2));
	}

}

그런 다음 I 메모리 DFS를 사용하여이를 분할 스플릿 마지막 지점으로 간주 할 수 있고, 방사 분할 공지 대칭축 앞으로 다음 수직 이등분선의 대칭 특성이 다른 분할 된 빔을 도출 될 수 있고 전체 복사도까지 하나의 대칭 복사에서 시작 밀어 넣습니다.

코드

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
struct point {
	int x, y;
	bool operator <(const point & p) const {
		if (x != p.x)return x < p.x;
		else return y < p.y;
	}
};
set<point> P;
int n;
int a[31];

int dx[] = { 0,1,1,1,0,-1,-1,-1 };
int dy[] = { 1,1,0,-1,-1,-1,0,1 };

void dfs(int x, int y, int index,int dir) {
	if (index > n) return;
	
	 
	dfs(x + dx[dir] * a[index], y + dy[dir] * a[index], index + 1 ,(dir + 1) % 8);
	//对称复制
	set<point> temp;
	for (auto &Q : P) {
		if (dir % 4 == 0) {
			temp.insert({ 2 * x - Q.x,Q.y });
		}
		else if (dir % 4 == 1) {
			temp.insert({ x + Q.y - y,y + Q.x - x });
		}
		else if (dir % 4 == 2) {
			temp.insert({Q.x,2 * y -Q.y });
		}
		else if (dir % 4 == 3) {
			temp.insert({ x + y - Q.y,y - Q.x + x });
		}
	}
	P.insert(temp.begin(), temp.end());
	
	for (int i = 0; i < a[index]; i++) {
		x = x + dx[dir];
		y = y + dy[dir];
		P.insert({ x,y });
	}

}
int main() {
	cin.sync_with_stdio(false);
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	dfs(0, 0, 0, 0);
	cout << P.size() << endl;
	return 0;
}

게시 21 개 원래 기사 · 원 찬양 5 · 조회수 783

추천

출처blog.csdn.net/weixin_44578615/article/details/104909815