HHTC_学校集训编程题目(6)(搜索)

HHTC_学校集训编程题目(6)(搜索)

Rock, Scissors, Paper

Bart’s sister Lisa has created a new civilization on a two-dimensional grid. At the outset each grid location may be occupied by one of three life forms: Rocks, Scissors, or Papers. Each day, differing life forms occupying horizontally or vertically adjacent grid locations wage war. In each war, Rocks always defeat Scissors, Scissors always defeat Papers, and Papers always defeat Rocks. At the end of the day, the victor expands its territory to include the loser’s grid position. The loser vacates the position.
Your job is to determine the territory occupied by each life form after n days.

Input

The first line of input contains t, the number of test cases. Each test case begins with three integers not greater than 100: r and c, the number of rows and columns in the grid, and n. The grid is represented by the r lines that follow, each with c characters. Each character in the grid is R, S, or P, indicating that it is occupied by Rocks, Scissors, or Papers respectively.

Output

For each test case, print the grid as it appears at the end of the nth day. Leave an empty line between the output for successive test cases.

Sample Input

2
3 3 1
RRR
RSR
RRR
3 4 2
RSPR
SPRS
PRSP

Sample Output

RRR
RRR
RRR

RRRS
RRSP
RSPR

这道题目貌似是模拟题,,,,,
就是石头剪刀布,,,上下左右进行比较,,,比较多少次
用一个暂时的数组存放比完之后的结果,然后再次进行的时候在赋给原来的数组
AC代码:

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

char a[105][105],b[105][105];
int n,m,k;
int d[4][2] = {1,0,-1,0,0,1,0,-1};

bool judge(int x,int y){
    if(x >= 0 && y >= 0 && x < n && y < m)
        return true;
    return false;
}

void dfs(int x,int y){
    for(int i=0;i<4;i++){
        int xx = x + d[i][0];
        int yy = y + d[i][1];
        if(judge(xx,yy)){
            if(a[x][y] == 'R' && a[xx][yy] == 'S')
                b[xx][yy] = 'R';
            else if(a[x][y] == 'S' && a[xx][yy] == 'P')
                b[xx][yy] = 'S';
            else if(a[x][y] == 'P' && a[xx][yy] == 'R')
                b[xx][yy] = 'P';
        }
    }
}

int main(){
    int T,f = 0;
    cin>>T;
    while(T--){
        if(f != 0)
            cout<<endl;
        memset(a,0,sizeof(a));
        cin>>n>>m>>k;
        for(int i=0;i<n;i++){
            getchar();
            for(int j=0;j<m;j++){
                cin>>a[i][j];
            }
        }
        memcpy(b,a,sizeof(a));
        while(k--){
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    dfs(i,j);
                }
            }
            memcpy(a,b,sizeof(b));
        }
        for(int i=0;i<n;i++)
            cout<<a[i]<<endl;
        f++;
    }
    return 0;
}

Can you find it?

Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate if you can find the three numbers Ai, Bj, Ck, which satisfy the formula Ai+Bj+Ck = X.

Input

There are many cases. Every data case is described as followed: In the first line there are three integers L, N, M, in the second line there are L integers represent the sequence A, in the third line there are N integers represent the sequences B, in the forth line there are M integers represent the sequence C. In the fifth line there is an integer S represents there are S integers X to be calculated. 1<=L, N, M<=500, 1<=S<=1000. all the integers are 32-integers.

Output

For each case, firstly you have to print the case number as the form “Case d:”, then for the S queries, you calculate if the formula can be satisfied or not. If satisfied, you print “YES”, otherwise print “NO”.

Sample Input

3 3 3
1 2 3
1 2 3
1 2 3
3
1
4
10

Sample Output

Case 1:
NO
YES
NO

就是在ABC三个序列中找使之等式Ai+Bi+Ci = x成立的数,
x为你输入的数,如果有YES,否则NO
直接变换公式,然后使用二分法,Ai + Bi = x - Ci
先把A和B先加起来,然后利用二分法去搜索~
AC代码:

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

int a[505],b[505],c[505];
int a_b[250005];

bool judge(int a_b[],int xx,int num){
    int left = 0;
    int right = num - 1;
    while(left <= right){
        int mid = (right + left) / 2;
        if(a_b[mid] == xx){
            return true;
        }
        if(a_b[mid] < xx)
            left = mid + 1;
        else
            right = mid - 1;
    }
    return false;
}

int main(){
    int A,B,C,S,k = 0;
    while(scanf("%d %d %d",&A,&B,&C) != EOF){
        for(int i=0;i<A;i++)
            scanf("%d",&a[i]);
        for(int i=0;i<B;i++)
            scanf("%d",&b[i]);
        for(int i=0;i<C;i++)
            scanf("%d",&c[i]);
        int num = 0;
        for(int i=0;i<A;i++){
            for(int j=0;j<B;j++){
                a_b[num++] = a[i] + b[j];
            }
        }
        sort(a_b , a_b + num);
        scanf("%d",&S);
        printf("Case %d:\n",++k);
        while(S--){
            int x,f = 0;
            scanf("%d",&x);
            for(int i=0;i<C;i++){
                int xx = x - c[i];
                if(judge(a_b,xx,num)){
                    cout<<"YES"<<endl;
                    f = 1;
                    break;
                }
            }
            if(f == 0){
                cout<<"NO"<<endl;
            }
        }
    }
    return 0;
}

N皇后问题

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

Input

共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。

Output

共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。

Sample Input

1
8
5
0

Sample Output

1
92
10

这道题目就是实打实的搜索题目,不过会超时
直接打表就AC了
AC代码:

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

int ans;
int a[15];

bool attack(int x0,int y0,int x1,int y1){
    if(x0 == x1 || y0 == y1)
        return true;
    if(x0 + y0 == x1 + y1 || x0 - y0 == x1 - y1)
        return true;
    return false;
}

void dfs(int x,int n){
    if(x == n){
        ans++;
        return ;
    }
    for(int i=0;i<n;i++){
        bool ok = true;
        for(int j=0;j<x;j++){
            if(attack(j,a[j],x,i)){
                ok = false;
                break;
            }
        }
        if(ok){
            a[x] = i;
            dfs(x+1,n);
        }
    }
}

int main(){
    int n;
    int a[15];
    for(int i=0;i<=10;i++){
        ans = 0;
        dfs(0,i);
        a[i] = ans;
    }
    while(scanf("%d",&n) && n != 0){
        printf("%d\n",a[n]);
    }
    return 0;
}

统计问题

在一无限大的二维平面中,我们做如下假设:
1、 每次只能移动一格;
2、 不能向后走(假设你的目的地是“向上”,那么你可以向左走,可以向右走,也可以向上走,但是不可以向下走);
3、 走过的格子立即塌陷无法再走第二次;

求走n步不同的方案数(2种走法只要有一步不一样,即被认为是不同的方案)。

Input

首先给出一个正整数C,表示有C组测试数据
接下来的C行,每行包含一个整数n (n<=20),表示要走n步。

Output

请编程输出走n步的不同方案总数;
每组的输出占一行。

Sample Input

2
1
2

Sample Output

3
7

这道题,直接使用搜索肯定是超市的,而且打表也会超时,
可以直接把数据抠出来,然后直接输出结果即可,
还有一种方法就是递推····
递推思路:
第n步,f(n) = a(n) + b(n);a(n)表示n步向上的走法,b(n)表示n步左右的走法,向上走的步数只有一种选择就是上一次的步数相加:a(n)=a(n-1)+b(n-1)(前(n-1)步内往上走的步数+前(n-1)步内往左或右的步数);又因为走过的不能返回,所以往左或右走只有一种方法,但向上走可以是左上和右上两种,因此b(n)=2*a(n-1)+b(n-1);化简:
f(n)=a(n)+b(n)=a(n-1)+b(n-1)+b(n-1)+2a(n-1)=3a(n-1)+2b(n-1)
f(n)=2f(n-1)+a(n-1)=2f(n-1)+(a(n-2)+b(n-2))=2f(n-1)+f(n-2)
AC代码(搜索):

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

int ans;
int d[3][2] = {0,-1,0,1,-1,0};
int vis[25][50];

void dfs(int cnt,int x,int y,int n){
    if(cnt == n)
        ans++;
    else
    {
        for(int i=0; i<3; i++)
        {
            int xx = x + d[i][0];
            int yy = y + d[i][1];
            if(!vis[xx][yy])
            {
                vis[xx][yy]=1;
                dfs(cnt+1,xx,yy,n);
                vis[xx][yy]=0;
            }
        }
    }

}

int main(){
    int n;
    int a[21] = {1,3,7,17,41,99,239,577,1393,3363,8119,19601,47321,114243,275807,665857,1607521,3880899,9369319,22619537,54608393};
    /*for(int i=0;i<=20;i++){
        ans = 0;
        memset(vis,0,sizeof(vis));
        vis[20][20] = 1;
        dfs(0,20,20,i);
        cout<<ans<<",";
    }*/
    int T;
    cin>>T;
    while(T--){
        int n;
        cin>>n;
        cout<<a[n]<<endl;
    }
    return 0;
}

AC代码(递推):

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

int a[21]= {0,3,7};

int main()
{
    int i,k,n;
    for (i=3; i<=20; i++)
        a[i]=2*a[i-1]+a[i-2];
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&k);
        printf("%d\n",a[k]);
    }
    return 0;
}

Sudoku

Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure. In some of the cells are written decimal digits from 1 to 9. The other cells are empty. The goal is to fill the empty cells with decimal digits from 1 to 9, one digit per cell, in such way that in each row, in each column and in each marked 3x3 subsquare, all the digits from 1 to 9 to appear. Write a program to solve a given Sudoku-task.
在这里插入图片描述

Input

The input data will start with the number of the test cases. For each test case, 9 lines follow, corresponding to the rows of the table. On each line a string of exactly 9 decimal digits is given, corresponding to the cells in this line. If a cell is empty it is represented by 0.

Output

For each test case your program should print the solution in the same format as the input data. The empty cells have to be filled according to the rules. If solutions is not unique, then the program may print any one of them.

Sample Input

1
103000509
002109400
000704000
300502006
060000050
700803004
000401000
009205800
804000107

Sample Output

143628579
572139468
986754231
391542786
468917352
725863914
237481695
619275843
854396127

就是填写数独~
直接使用dfs即可完成~
AC代码:

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

int num[9][9];
char s[9][9];
bool sign = false;

bool check(int n, int key){
    //判断key在横列是否合法
    for(int i=0;i<9;i++){
        int j = n / 9;
        if(key == num[j][i])
            return false;
    }
    //判断key在竖列是否合法
    for(int i=0;i<9;i++){
        int j = n % 9;
        if(key == num[i][j])
            return false;
    }
    int x = n / 9 / 3 * 3;      //左顶点竖坐标
    int y = n % 9 / 3 * 3;      //左顶点横坐标
    for(int i=x;i<x+3;i++){     //判断小矩阵是否合法
        for(int j=y;j<y+3;j++){
            if(key == num[i][j])
                return false;
        }
    }
    return true;
}

void dfs(int n){
    if(n > 80){
        sign = true;
        return ;
    }
    if(num[n/9][n%9] != 0){
        dfs(n + 1);
    }else{
        for(int i=1;i<10;i++){
            if(check(n,i)){
                num[n/9][n%9] = i;
                dfs(n + 1);
                if(sign == true)
                    return ;
                num[n/9][n%9] = 0;
            }
        }
    }
}

int main(){
    int T;
    cin>>T;
    while(T--){
        sign = false;
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                cin>>s[i][j];
                num[i][j] = s[i][j] - '0';
            }
        }
        dfs(0);
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                cout<<num[i][j];
            }
            cout<<endl;
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值