题意:由6n^2个小三角形组成的正六边形,问你用两个小三角菱形去填满有多少种方法

解题思路:状态压缩+dp(因为只有一部分小三角形对下一层有影响)。。分上下讨论(不同的规则),情况比较多!

解题代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<map>
  4 #include<vector>
  5 #include<cmath>
  6 #include<cstdlib>
  7 #include<stack>
  8 #include<queue>
  9 #include <iomanip>
 10 #include<iostream>
 11 #include<algorithm>
 12 #pragma comment(linker,"/STACK:102400000,102400000")
 13 
 14 using namespace std ;
 15 
 16 long long pos[100];
 17 long long num[30];
 18 long long dp[20][40000]; 
 19 long long row , zt , limits[30] ,n; 
 20 long long su[30];
 21 void dfs(long long  pop,long long status)
 22 {
 23     if(pop == su[row+1] )
 24     {
 25         dp[row+1][status] +=  dp[row][zt];
 26         return ;
 27     }
 28 
 29     if(row+1 <= n){
 30 
 31         if(pop % 2 == 0 ){      
 32             if(pop + 1 < su[row+1] && num[pop] == 0 ) 
 33             {   
 34                 dfs(pop+2,status);
 35                 dfs(pop+1,status+pos[pop/2]);
 36             }
 37             else 
 38                 dfs(pop+1,status+pos[pop/2]);
 39         }
 40         else {
 41             if(num[pop-1])
 42                 dfs(pop+1,status);
 43             else {
 44                 dfs(pop+2,status);
 45             }
 46         }
 47 
 48     }
 49     else {
 50         if(pop % 2 == 1 ){
 51             if(row == n?num[pop+1] == 0: num[pop+2] ==  0)
 52             {   
 53                 if(pop + 2 == su[row+1])
 54                     dfs(pop+2,status);
 55                 else{
 56                     dfs(pop+2,status);
 57                     dfs(pop+1,status + pos[pop/2]);
 58                 }
 59             }
 60             else
 61                 dfs(pop+1,status+pos[pop/2]);
 62         }
 63         else {
 64             if(row == n ? num[pop]:num[pop+1])
 65                 dfs(pop+1,status);
 66             else {
 67                 if(pop + 1 < su[row+1])
 68                     dfs(pop+2,status);
 69             }
 70 
 71         }    
 72 
 73     }
 74 
 75 }
 76 void change(long long k)
 77 {
 78     memset(num,0,sizeof(num));
 79     long long m = k ; 
 80     long long t = -2 ; 
 81     while(m)
 82     {
 83         t = t+2; 
 84         num[t] = m%2;
 85         m = m/2;
 86     }
 87 
 88 } 
 89 void change1(long long k)
 90 {
 91     memset(num,0,sizeof(num));
 92     long long m = k ; 
 93     long long t = -1 ; 
 94     while(m)
 95     {
 96         t = t+2; 
 97         num[t] = m%2;
 98         m = m/2;
 99     }
100 } 
101 int main()    
102 {
103     pos[0] = 1;
104     for(long long i = 1;i <= 18; i ++ )
105     {
106         pos[i] = 2* pos[i-1];    
107     }
108 
109     memset(limits,0,sizeof(limits));
110     int t  = 0;
111     while(scanf("%lld",&n)!=EOF)
112     {
113         t ++;
114         for(long long i = 1;i <= n;i ++)
115             limits[i] = n+i;
116         for(long long i = n+1 ;i <= 2*n ;i ++)
117             limits[i] =  limits[2*n -i+1] -1;
118         for(long long i = 1;i <= n;i ++)
119             su[i] = 2*(n+i) - 1; 
120         for(long long i = n+1; i <= 2*n ;i ++)
121             su[i] =  su[2*n-i+1];
122 
123 
124 
125         memset(dp,0,sizeof(dp));
126         dp[0][0] = 1; 
127         for(row = 0 ; row < 2*n ; row ++)
128             for(zt = 0 ; zt < pos[limits[row]+1]; zt ++)
129             {
130                 if(dp[row][zt])
131                 {
132                     if(row <= n) 
133                         change(zt);
134                     else 
135                         change1(zt);
136                     dfs(0,0); 
137                 }
138             }
139         if(t!= 1 )
140             printf("\n");
141 
142         printf("%lld\n",dp[2*n][0]);
143     }
144     return 0 ; 
145 
146 }
View Code

ps:AC这道题 这是今天最爽的时候

posted on 2013-09-10 20:13  dark_dream  阅读(338)  评论(0编辑  收藏  举报