uvalive 4031 - Integer Transmission

来源:互联网 发布:飞越官场星河源码 编辑:程序博客网 时间:2024/06/09 16:53

这道题。。最开始看的时候不知道怎么做。。经过将讲解。。开始理解了。。

数位dp

状态定义大概是这样子的。。 f[i][j][k] (其实可以省略一维,不过空间足够,写起来更方便)第i个位置,用到第j个0,第i个1了。

呃。。我听了状态的定义还是不太明白。。

然后做法是这个样子的:从二进制低位到高位依次填数字(0或1),当然,填数字是有限制的。。。

考虑原数字k的二进制形势,举个例子:当11101(2)=k , d=2 的时候 最左边的1是不能够移到0的右边的,而第二个1就可以,那么构成的新的数字就是11011(2),可以看成是把1弄到了0的右边。。。也就是说,当 当前的1的位置+d > 当前0的位置 的时候 能够将1移动到0的右边,就能够构成新的数字了嘛 = =。。

另外两个问题就不讨论了。。

下面是代码

#include<cstdio>#include<cstring>#include<algorithm>#define LL unsigned long longusing namespace std ;LL num0 , num1 , n , d , k , T;bool vis[200][100][100] ;LL f[200][100][100] ;int s0[200] , s1[200] ;LL dfs(int p,int p0,int p1) {//if(p == n && p0 == num0 && p1 == num1) return 1 ;LL &x = f[p][p0][p1] ;if(vis[p][p0][p1]) return x ;vis[p][p0][p1] = true ; x = 0 ; bool op = true ;if(p0 < num0 && p1 < num1) {if(s0[p0] + d < s1[p1]) x = dfs(p+1 , p0+1 , p1) , op = false ;else if(s1[p1] + d < s0[p0]) x = dfs(p+1 , p0 , p1+1) , op = false ;}if(op) {if(p0 < num0) x = dfs(p+1 , p0+1 , p1) ;if(p1 < num1) x += dfs(p+1 , p0 , p1+1) ;}return x ;}int main() {while(~scanf("%llu",&n)) {if(!n) break ;scanf("%llu%llu",&d,&k) ;num0 = num1 = 0 ;for(int i = 0 ; i < n ; i++) {if(k&1) s1[num1++] = i ;else s0[num0++] = i ;k >>= 1 ;}memset(vis , 0 , sizeof(vis)) ;memset(vis[n] , 1 , sizeof(vis[n])) ;memset(f[n] , 0 , sizeof(f[n])) ;f[n][num0][num1] = 1 ;LL ans0 , ans1 = 0 , ans2 = 0;ans0 = dfs(0 , 0 , 0) ;int a = 0 , b = 0 ;for(int i = 0 ; i < n ; i++) {if(a < num0 && b < num1 && s0[a] + d < s1[b]) {a++ ; continue ; }if(b < num1) { b++ ; ans1 |= 1llu<<i ; continue ; }a++ ;}a = b = 0 ;for(int i = 0 ; i < n ; i++) {if(a < num0 && b < num1 && s1[b] + d < s0[a]) {ans2 |= 1llu << i ;b++ ; continue ;}if(a < num0) {a++ ; continue ;}b++ ; ans2 |= 1llu << i ;}printf("Case %d: %llu %llu %llu\n",++T,f[0][0][0],ans1,ans2) ;}return 0 ;}


0 0