uva 188 - Perfect Hash

点击打开链接


题目意思: 说这个题目之前先让我喷喷,太尼玛恶心了一道水题装B 的好像很有技术含量,真的是恶心。

题目给定一个字符串。每一个字符串由多个单词组成,现在有一个计算法则“ a = 1 , b = 2 ...... z = 26 ,‘a’ = 1 , “bz” = 26*32^0 + 2*32^1 = 90 类似32进制的转换” 然后要求我们去求出每一单词的值w ,排序满足 W1<W2<.......<Wn.

现在要求我么能否找到一个整数C ,使得:1 对于所以的Wi,Wj而言都有 C/WI % n != C/Wj % n;2 并且C是所以Wi中至少一个的倍数 3 如果有出现C/WI % n = C/Wj % n 时候就要令 C = Min( (C/WI+1) * Wi , (C/Wj+1) * Wj ); 直到求出最小的C


解题思路: 我么初始化C = 1 ;然后去做循环判断,由于要比较要两重循环,只要我们判断到 C/WI % n = C/Wj % n 我么就要去递归进行下一轮的判断,如果当找到C后就不会去 递归返回的时候直接return即可。对于单个字符提取,可以用split函数


代码:

//分割字符串我们使用split函数
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;
#define MAXN 10000

char ch[MAXN] , Ch[MAXN];
int  w[20];
int  C , k;

//求出最小值
inline int Min(int a , int b){
    return a < b ? a : b;
}

//判断求最小C
void solve() {
    for (int i = 0 ; i < k ; i++) {
        for (int j = i + 1 ; j < k ; j++) {
            if ((C/w[i])%k == (C/w[j])%k){ 
                C = Min((C/w[i]+1)*w[i] , (C/w[j]+1)*w[j]);
                solve();//递归
                return;//递归回来后说明找到了C则直接退出
            }
        } 
    }
}

//主函数
int main() {
    //freopen("input.txt" , "r" , stdin);
    int i , t;
    while (gets(ch)) {
        memcpy(Ch , ch , sizeof(ch));
        memset(w, 0, sizeof (w));
        const char* split = " " ; char *p;
        p = strtok(ch, split);
        int len = strlen(p);
        for (k = 0,i = 0; i < len; i++) {
            t = p[i] - 'a' + 1;
            w[k] += t * pow(32, len - 1 - i);
        }
        k++;
        while (p != NULL) {
            p = strtok(NULL, split);
            if (p == NULL) break;
            int len = strlen(p);
            for (i = 0; i < len; i++) {
                t = p[i] - 'a' + 1;
                w[k] += t * pow(32, len - 1 - i);
            }
            k++;
        }
        sort(w, w + k);
        C = 1 ; solve();//C初始化为1,不为0即可
        printf("%s\n" , Ch);
        printf("%d\n\n" , C);
    }
    return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值