Noip 시뮬레이션 훈련 2

Noip 시뮬레이션 훈련 2

  • (260)가 부족합니다. T1 (100), T2 (50), T3 (60)
  • I 260 개정 70 최초
  • 쉽게

T1 : 지뢰 찾기

기술

  • N × M (1≤N, M≤100)는 배리어 영역의 격자 영역으로 표시된 "#"을 메쉬 그리드는 숫자 지뢰로 표시되는 디지털 데이터는 광산의 영역이다. 도리깨 차량이 왼쪽 상단 모서리에서 시작하여, 오직 오른쪽으로 이동하거나 아래로 내 통관 차량이 위험을 입력 할 수 없습니다,뿐만 아니라 그것은 그리드 지뢰가 제거됩니다 여행했다. 당신의 작업은 그리드의 왼쪽 상단 모서리에서 출발 찾는 프로그램을 컴파일하는 것입니다 (1, 1) 그리드 (N, M)와 광산 삭제 경로의 대부분의 오른쪽 하단에 도달한다. 다음은 최적의 경로는 6 개 demining 광산을 해제 할 수 있습니다, 4 × 5의 샘플 그리드입니다.

    1
    # #
    # #
    # # 1

입력

  • 입력 파일의 첫 번째 라인은 두 숫자 사이의 공간에 의해 분리 된 두 정수 N과 M을 mine.in된다. 다음 N 개의 행은 음수 영역은 배리어 영역이 있음을 나타내는 상기 M 정수를 갖는 각 행은, 음이 아닌 개수 지뢰밭을 표시하고, 정수는 개의 인접한 정수의 동일한 행이 해당 지역에서 광산의 총 수를 나타내고, 별도의 공간.

산출

  • 출력 파일 mine.out 하나의 행 노선의 demining이 존재하지 않는 경우, 오른쪽 하단, 출력 "응답 없음", 또는 출력 클리어 광산의 최대 수를 나타내는 정수로 왼쪽 상단에서 어떤 경로가 없다는 것을.

샘플 입력

4 5

0 1 0 0 0

2 3 -1 0 -1

0 3 0 -1 -1

-1 -1 0 1 0

샘플 출력

6

해결 방법 :

  • DP. 그러나 70을했다. 상황의 시간 생각에 무대 조금 올 것이다,하지만 단지 코드를 구현하지, 당연하게 받아,이 문제가되지한다고 생각합니다. 따라서, 업데이트 된 상태 가능성에주의를 기울를 DP 후

  • 그래서 :
    1. 그 다양한 조건을 참고 : 경계 조건을 업데이트 상태 초기화
    2. 당연하지 마십시오
#include <iostream>
#include <cstdio>
#define maxn 105
using namespace std;

int n, m;
int a[maxn][maxn], f[maxn][maxn];
bool can[maxn][maxn];

int main()
{
    can[0][1] = can[1][0] = 1; //初始化!!
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
        {
            cin >> a[i][j];
            if(a[i][j] < 0) a[i][j] = -1;
        }
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            if(a[i][j] != -1)
            {
                if(can[i - 1][j] || can[i][j - 1]) can[i][j] = 1;
                if(can[i - 1][j] || can[i][j - 1]) f[i][j] = max(f[i - 1][j], f[i][j - 1]) + a[i][j];
            }
    if(!can[n][m]) cout << "No answer";
    else cout << f[n][m];
    return 0;
}

T2 : 시티 투어

기술

  • L은 현대 도시 관광 도시 간 거리의 직선 스트립 규칙 직사각형 네트워크이며, 각 거리가 정수로 넘버링되고, 도시 된 바와 같이, 네트워크는 두 거리 교차로의 교차점을 나타낸다 거리 번호, 수직 점의 거리 번호)의 수준은 도심의 규정 좌표 점 (0으로 표현 좌표 :( 0). ()은 중요하지 않습니다 아무도 없다

    시내 중심에서, 네트워크를 통해 거리를 따라 모든 단계 :이 도시는, 그들은 다음과 같은 규칙을 개발 한 여행을 더 재미있게 만들기 위해 지나갈 수는 M 횡단 신호등 유지 보수 시스템 및 배치 도로를 봉쇄, 도시의 도보 여행 관광객의 그룹을 가지고 세포는 4 개 방향을 취할 수있는 첫 번째 단계에 더하여, 이전 턴 기반의 단계별 나머지 좌우로 90 개도, 첫번째 단계는 N은 (0, 0) 동안의 시작점으로 되돌아 필요 중간 점 나머지 그것은 반복되지 않을 수 있습니다 .

    위의 그림에서, 다시 처음으로 세 가지 조치를 취할 수 없다 (0, 0)에서 시작하고, 두에 4 단계 경로의 처음으로 돌아가 : 한 것은 : (0,0) → (-1,0) → (-1,1) → (0.1) → (0,0),

    그리고 다른 하나는 다음과 같습니다 (0,0) → (0.1) → (-1,1) → (-1,0) → (0,0).

    당신의 임무는 주어진 수 N, M 및 M 번째 장애물 배포, 프로그램의 모든 여행 경로를 찾을 수 있다는 것입니다.

입력

  • 입력 파일의 첫 번째 라인은 N 단계의 투어 코스를 나타내는 두 정수 N과 M, sight.in이고

    수는 M과 장애물의 개수, 상기 0≤N≤40,0≤M≤50를 나타낸다. 다음에 M 개의 행은 각 행의 좌표 공간에 의해 분리 된 두 개의 인접하는 정수 사이의 두 정수 장애물에 의해 주어진다.

산출

  • 출력 파일은 하나의 행, 여행 경로의 요구 사항을 충족하기 위해 주어진 수를 sight.out.

샘플 입력

4 2

0 -1

1 0

샘플 출력

해결 방법 :

  • 검색, 가지 치기가 필요합니다. 그러나 잘못된 문제를 첫번째 ... "남아있는 점을 반복 할 수없는 가운데," 이 말은 보지 못했다. 그러나 첫 번째 개정 이후 단 한 점을 얻었다. 아이디어 (가지 치기가 줄 생각 안) 가지 치기를 기대하지 않았기 때문에 가지 치기는 "판사 후 갈 곳이 다시 시작 충분히 몇 가지 단계가 있습니다"하지만, 단계의 수는 힘들었다 푸시를 계산 오랜 시간 동안 (프로그램 참조). 그러나 제 2 보정, 또는 단지 하나의 포인트의 완료 후에. 그럼지도가 너무 느린 경우 궁금해? 그런 배열 동작 양수 후 밖으로 모두 존재의 좌표로 변환.

  • 그래서 :

    1. 전체 번역을 조정할 수 음수가있다

    2. 그것은 치기 가지 치기를 검색 할 수 있습니다

    3. STL은 신중해야

#include <iostream>
#include <cstdio>
#define maxn 2005
#define k 100 //平移系数
using namespace std;

int mp[maxn][maxn], need[maxn][maxn];
bool vis[maxn][maxn];
int t, n, ans;
int dx[5][3] = {
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 1, -1},
{0, -1, 1}
};
int dy[5][3] = {
{0, 0, 0},
{0, -1, 1},
{0, 1, -1},
{0, 0, 0},
{0, 0, 0}
};

inline int cal(int turn, int flag)
{
    if(flag == 1)
        {if(turn == 1) return 3; if(turn == 2) return 4; if(turn == 3) return 2; if(turn == 4) return 1;}
    else
        {if(turn == 1) return 4; if(turn == 2) return 3; if(turn == 3) return 1; if(turn == 4) return 2;}
    return 0;
}

inline int call(int x, int y) {
    x = abs(x - k), y = abs(y - k);
    if((x % 2 == 0 && y % 2 == 0) || (x % 2 != 0 && y % 2 != 0)) return 2 * x;
    else return 2 * (x - 1) + 1;
}

inline void dfs(int x, int y, int step, int turn)
{
    if(mp[x][y] == -1) return;
    if(!need[x][y]) need[x][y] = call(x, y);
    if(step + need[x][y] > t + 1) return;
    if(step > t)
    {
        if(x == k && y == k) {ans++; return;}
        return;
    }
    int xx, yy;
    xx = x + dx[turn][1], yy = y + dy[turn][1];
    if(!vis[xx][yy])
    {
        vis[xx][yy] = 1;
        dfs(xx, yy, step + 1, cal(turn, 1));
        vis[xx][yy] = 0;
    }
    if(xx == k && yy == k && step == t) dfs(xx, yy, step + 1, cal(turn, 1));
    xx = x + dx[turn][2], yy = y + dy[turn][2];
    if(!vis[xx][yy])
    {
        vis[xx][yy] = 1;
        dfs(xx, yy, step + 1, cal(turn, 2));
        vis[xx][yy] = 0;
    }
    if(xx == k && yy == k && step == t) dfs(xx, yy, step + 1, cal(turn, 2));
}

int main()
{
    freopen("sight.in", "r", stdin);
    freopen("sight.out", "w", stdout);
    
    vis[k][k] = 1;
    cin >> t >> n;
    for(int i = 1; i <= n; i++)
    {
        int x, y;   cin >> x >> y;
        mp[x + k][y + k] = -1;
    }
    vis[k][-1 + k] = 1, dfs(k, -1 + k, 2, 3), vis[k][-1 + k] = 0;
    vis[k][1 + k] = 1, dfs(k, 1 + k, 2, 4), vis[k][1 + k] = 0;
    vis[-1 + k][k] = 1, dfs(-1 + k, k, 2, 1), vis[-1 + k][k] = 0;
    vis[1 + k][k] = 1, dfs(1 + k, k, 2, 2), vis[1 + k][k] = 0;
    cout << ans;
    return 0;
}

프라임 파트너

기술

  • 암호화 말한다 등 2, 5, 6, 13 우리는 "주요 파트너"전화를 모두 양의 정수 및 소수 인은, 통신에 적용 할 수 있습니다. 2,5,6,13, 경우 : 이제 암호는 예를 들어, 네 개의 양의 정수가, 어떤 양의 정수 n을왔다, 여러 쌍의 '주요 파트너 "을 선택, 프로그램을 설계 기법의 다양한 선택하는 법을 배워야 (2) 5,6 및 13는 두 "프라임 파트너"방식까지 "호출"프라임 파트너 "로 구성 될 수 얻어지는 구성하면서도 5 및도 6은"프라임 파트너 "의 세트를 제공하기 위해 그룹들로 분할 될 수있다 최고의 솔루션 최적의 솔루션 "물론, 당신은을 찾으려는 비밀번호를 배울". "

입력

  • n이 400 이상이 아닌 양의 정수 N, prime.in 입력 파일의 첫 번째 라인은 자연수의 수가 선택 될 나타낸다. 두 번째 행은 공백 개의 인접한 서브 숫자 사이하게는 30,000 이상, N의 양의 정수를 준다

    를 엽니 다.

산출

  • 출력 파일은 하나 개의 행을 prime.out 쌍의 수의 당신이 양식을 얻은 "주요 파트너"는 "최적의 솔루션"을 제공합니다.

샘플 입력

4

2 5 6 13

샘플 출력

해결 방법 :

  • 다음과 같이 원래의 아이디어입니다 :
    • 두와 소수의 수, 양쪽의도 번호
    • 도 완료하면 그래프가 형성된다
    • 이 그림은) 나무 :( 증거는 다음 사실이다
    • A + B는 알려진 소수, B + C = 소수 =; Q A + C를 =?
    • 홀수 소수의 A, B 때문에, 각각 홀수 및 짝수
    • A는 홀수 C 홀수가 도입 될 수있을 때 그 때문에 C = A + 짝수! = 소수
    • A는 짝수, C 짝수가 도입 될 수 인 경우 그 C가 = A + 짝수! = 국무 수 있도록
    • 결합의 합에있어서, A + C = 번호
    • 그래서 그림의 의미에서, 거기에는 링이 없기 때문에이 나무도
    • 그런 다음 그림은 나무 뒤에, 나는이 나무의 긴 체인을 취할 수 대답이 가장 긴 체인 / 2 (내림)
  • 그러나, 전체 버스트.

  • A = 1, B = 1, C는 시간 = 1, A + C = 프라임!이 존재하므로,도 링 상기 체결 푸시 모순 때 때문에!

    그래서이 아이디어는 개선 될 필요가있다.

  • 이분 그래프 매칭의 긍정적 인 솔루션 : 데이터가 1이 아닌 경우, 내 알고리즘이 가능하다. 헝가리 알고리즘의 긍정적 인 솔루션을 가진 파트너를 찾기 위해 모든 심지어 다른 측면에서, 그 홀수 쪽을 모두 사용할 수있는 홀수, 홀수 하나의 파트너를 찾을 수없는 경우가있는 경우, 다음 (1), 그 다음 하나의 변수에 축적. 성공적으로 페어링의 총 수, 플러스 2로 나눈 짝 (1)의 총 수, 대답이다.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define maxn 405
using namespace std;

int n, cnt1, cnt2, ans, tot;
int a[maxn], b[maxn], mat[maxn];
bool vis[maxn];

bool cal(int x, int y)
{
    int t = x + y, last = (int)sqrt(t);
    for(int i = 2; i <= last; i++)
        if(t % i == 0) return 0;
    return 1;
}

bool find(int x)
{
    for(int i = 1; i <= cnt2; i++)
        if(cal(a[x], b[i]) && !vis[i])
        {
            vis[i] = 1;
            if(!mat[i] || find(mat[i]))
            {
                mat[i] = x;
                return 1;
            }
        }
    return 0;
}

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        int t;  cin >> t;
        if(t % 2 == 0) b[++cnt2] = t;
        else a[++cnt1] = t;
        if(t == 1) tot++;
    }
    for(int i = 1; i <= cnt1; i++)
    {
        memset(vis, 0, sizeof(vis));
        if(find(i))
        {
            ans++;
            if(a[i] == 1) tot--;
        }
    }
    cout << ans + (int)(tot / 2) << endl;
}

추천

출처www.cnblogs.com/BigYellowDog/p/11129905.html