UVALive 6934 Good morning! 打表判断

题目链接

今天打得还算顺利,这题有坑,写一下吧,由于wcr小朋友凭借他聪明的小脑袋先开了这题,,导致后面许多队不幸掉坑,题意大概就是一个键盘一样的东西,你每次只能往下或者往右挪动手去按数字,一个数字可以按多次,给定一个数字n,求能按到的距离n最近的数字,这题主要就是坑在,如果距离相当,在取数字的时候,是没有上界的,虽然给出的数字是到两百,但是按的数字可以大于两百。

这题本来我想打表,从每个数字出发搜索一下能到达的数字然后进行标记,wwz同学机智的想到用一个二维数组vis,vis[i][j]表示数字i是否能排在j前面,然后就是从给定的数字开始往左右两侧搜索是否能按,对于每个数字,判断它的相邻两位是否满足条件,就可以了。

<span style="font-size:18px;">#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<list>
#include<cmath>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
const int INF = 100000000;
const long long maxn = 111;
int T,n,m,k,vis[20][20];
void init() {
    memset(vis,-1,sizeof(vis));
    for(int i=1;i<=9;i++) {
        for(int j=1;j<i;j++) vis[i][j] = 0;

        if(i == 1 || i == 4 || i == 7) continue;
        else if(i == 2 || i == 5 || i == 8) {
            vis[i][1] = vis[i][4] = vis[i][7] = 0;
        }
        else {
            vis[i][1] = vis[i][4] = vis[i][7] = vis[i][2] = vis[i][5] = vis[i][8] = 0;
        }
    }
    vis[3][0] = vis[6][0] = vis[9][0] = 0;
    for(int i=1;i<=9;i++) vis[0][i] = 0;
}

int main() {
    scanf("%d",&T);
    init();
    while(T--){
        scanf("%d",&k);
        bool ok = false;
        int ans = 0;
        for(int i=0;i<=k;i++) {
            int v1 = k - i , v2 = k + i;
            if(v2 <= 200) {
                if(v2<10) { ok = true; ans = v2; break; }
                else if(v2 < 100) { if(vis[v2/10][v2%10]) { ans = v2; break; } }
                else { if(vis[v2/100][(v2-v2/100*100)/10]&&vis[(v2-v2/100*100)/10][v2%10]) {ans = v2; break;} }
            }
            if(v1 >= 0) {
                if(v1<10) { ok = true; ans = v1; break; }
                else if(v1 < 100) { if(vis[v1/10][v1%10]) { ans = v1; break; } }
                else { if(vis[v1/100][(v1-v1/100*100)/10]&&vis[(v1-v1/100*100)/10][v1%10]) {ans = v1; break;} }
            }
         }
         printf("%d\n",ans);
    }
    return 0;
}</span>
还有一个人用的做法就是我说的那样,先搜索一下,把能到达的数字放到数组里,然后lower_bound就可以了。

<span style="font-size:18px;">#include <iostream>
#include <set>
using namespace std;
set<int> s;
set<int>::iterator p;

void dfs(int m, int n, int d) {
    if(m < 201)
        s.insert(m);
    else return;
    if(n == 11)
        n = 0;
    if(d == 3 || n > 9 )
        return;
    dfs(m * 10 + n, n, d + 1);
    if(n % 3)
        dfs(m, n + 1, d);
    if(n)
        dfs(m, n + 3, d);
}
int main() {
    int t, n, m;
    dfs(0, 1, 0);
//    for(p = s.begin(); p != s.end(); p++)
//        cout << *p << endl;
    cin >> t;
    while(t--) {
        cin >> n;
        p = s.lower_bound(n);
        m = *p;
        if(p != s.begin()) {
            p--;
            if(n - *p < m - n)
                m = *p;
        }
        cout << m << endl;
    }
    return 0;
}</span>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值