[CF Gym 100827E] Hill Number [2014-2015 ACM-ICPC Pacific Northwest Regional Contest E]

来源:互联网 发布:交叉熵 圣经网络 编辑:程序博客网 时间:2024/05/29 13:10

题意

给定一个数字N,它是hill-number当且仅当它不存在“低谷”,低谷形如如“101”,“555444555”。若N为hill-number输出比它小的hill-number个数,否则输出-1。

题解

动态规划。
设计状态f(当前位置,以k结尾,是否有限制,上升或下降)。
当前位置:从左向右枚举
以k结尾:枚举0-9
是否有限制:指是否这一位及之前位置上所有数字都是给出数字对应位置上的数,是否有限制需要分别处理
上升或下降:可以预料hill-number一定是水平,一直增,先增后减,一直减这几种情况
转移很好想但比较麻烦。
由于比较懒直接用代码表示

// dont have limitRep (k1,0,9) {    if (f[up][unlim][k1][i]) {        Rep (k2,k1,9)            f[up][unlim][k2][i+1] += f[up][unlim][k1][i] ;        rep (k2,0,k1)            f[down][unlim][k2][i+1] += f[up][unlim][k1][i] ;    }    if (f[down][unlim][k1][i])        Rep (k2,0,k1)            f[down][unlim][k2][i+1] += f[down][unlim][k1][i] ;}// have limk1 = str[i] ;if (f[up][lim][k1][i]) {    rep (k2,str[i],str[i+1])        f[up][unlim][k2][i+1] += f[up][lim][k1][i] ;    if (str[i+1] >= str[i])        f[up][lim][str[i+1]][i+1] += f[up][lim][k1][i] ;    if (str[i+1] < str[i])        f[down][lim][str[i+1]][i+1] += f[up][lim][k1][i] ;    k2 = k1-1 ;    if (k2 >= str[i+1]) k2 = str[i+1]-1 ;    while (k2 >= 0)        f[down][unlim][k2][i+1] += f[up][lim][k1][i] , k2 -- ;}if (f[down][lim][k1][i]) {    if (str[i+1] <= str[i])        f[down][lim][str[i+1]][i+1] += f[down][lim][k1][i] ;    k2 = k1 ;    if (k2 >= str[i+1]) k2 = str[i+1]-1 ;    while (k2 >= 0)        f[down][unlim][k2][i+1] += f[down][lim][k1][i] , k2 -- ;}

代码

/****************************************\* Author : ztx* Title  : E - Hill Number* ALG    :* CMT    :* Time   :\****************************************/#include <cstdio>#define Rep(i,l,r) for(i=(l);i<=(r);i++)#define rep(i,l,r) for(i=(l);i< (r);i++)#define Rev(i,r,l) for(i=(r);i>=(l);i--)#define rev(i,r,l) for(i=(r);i> (l);i--)typedef long long ll ;typedef double lf ;int CH , NEG ;template <typename TP>inline void read(TP& ret) {    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;    if (CH == '-') NEG = true , CH = getchar() ;    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;    if (NEG) ret = -ret ;}template <typename TP>inline void readc(TP& ret) {    while (ret=getchar() , ret<'!') ;    while (CH=getchar() , CH>'!') ;}template <typename TP>inline void reads(TP *ret) {    ret[0]=0;while (CH=getchar() , CH<'!') ;    while (ret[++ret[0]]=CH,CH=getchar(),CH>'!') ;    ret[ret[0]+1]=0;}#include <cstring>#include <algorithm>#define  maxn  77LLint str[maxn] ;inline bool hill(int *str) {    if (str[0] < 3) return true ;    int i , down = 0 , up = 0 , sta = 0 ;    bool ok = false ;    Rep (i,2,str[0]) {        if (str[i-1] == str[i]) continue ;        if (str[i-1] > str[i]) {            if (sta != -1) down ++ ;            sta = -1 ;        } else {            if (sta != 1) up ++ ;            if (!sta) ok = true ;            sta = 1 ;        }    }    if (down==1 && up==1 && ok) return true ;    if (down+up < 2) return true ;    return false ;}/*int str2[maxn] ;inline void calc() {    int ans = 1 , i , j , n = 0 ;    Rep (i,1,str[0]) n = n*10+str[i]-'0' ;    rep (i,1,n) {        str2[0] = 0 ;        j = i ;        while (j) {            str2[++str2[0]] = j%10 ;            j /= 10 ;        }        Rep (j,1,str2[0]/2)            std::swap(str2[j],str2[str2[0]+1-j]) ;        if (hill(str2)) ans ++ ;    }    printf("%d\n", ans) ;}*/ll ans ;ll f[2][2][10][maxn] ;// f[up down][lim][k][cur]#define  up    1#define  down  0#define  lim   1#define  unlim 0inline void calc() {    memset(f,0,sizeof f) ;    int i , k1 , k2 ;    Rep (i,1,str[0]) str[i] -= '0' ;    rep (i,0,str[1]) f[up][unlim][i][1] = 1 ;    f[up][lim][str[1]][1] = 1 ;    rep (i,1,str[0]) {        // dont have limit        Rep (k1,0,9) {            if (f[up][unlim][k1][i]) {                Rep (k2,k1,9)                    f[up][unlim][k2][i+1] += f[up][unlim][k1][i] ;                rep (k2,0,k1)                    f[down][unlim][k2][i+1] += f[up][unlim][k1][i] ;            }            if (f[down][unlim][k1][i])                Rep (k2,0,k1)                    f[down][unlim][k2][i+1] += f[down][unlim][k1][i] ;        }        // have lim        k1 = str[i] ;        if (f[up][lim][k1][i]) {            rep (k2,str[i],str[i+1])                f[up][unlim][k2][i+1] += f[up][lim][k1][i] ;            if (str[i+1] >= str[i])                f[up][lim][str[i+1]][i+1] += f[up][lim][k1][i] ;            if (str[i+1] < str[i])                f[down][lim][str[i+1]][i+1] += f[up][lim][k1][i] ;            k2 = k1-1 ;            if (k2 >= str[i+1]) k2 = str[i+1]-1 ;            while (k2 >= 0)                f[down][unlim][k2][i+1] += f[up][lim][k1][i] , k2 -- ;        }        if (f[down][lim][k1][i]) {            if (str[i+1] <= str[i])                f[down][lim][str[i+1]][i+1] += f[down][lim][k1][i] ;            k2 = k1 ;            if (k2 >= str[i+1]) k2 = str[i+1]-1 ;            while (k2 >= 0)                f[down][unlim][k2][i+1] += f[down][lim][k1][i] , k2 -- ;        }    }    ans = -1 ;    Rep (i,0,9) {        ans += f[up][lim][i][str[0]] ;        ans += f[down][lim][i][str[0]] ;        ans += f[up][unlim][i][str[0]] ;        ans += f[down][unlim][i][str[0]] ;    }    printf("%lld\n", ans) ;}int main() {int T ;//    #define READ    #ifdef  READ        freopen(".in" ,"r",stdin ) ;        freopen(".out","w",stdout) ;    #endif    read(T) ;    while (T -- ) {        reads(str) ;        if (!hill(str)) puts("-1") ;        else calc() ;    }    #ifdef  READ        fclose(stdin) ; fclose(stdout) ;    #else        getchar() ; getchar() ;    #endif    return 0 ;}
0 0
原创粉丝点击