【LOJ#10172】涂抹果酱

尽管本题依旧是状压dp,但是不同的是本题的状态无法用二进制表示,而需要三进制。三进制特殊的地方在于位运算符全都不能用了,因此本题比往常的题目多了一部分,就是手写判断,而不是直接&,|,^.

可喜的是,本题状态定义极其简单,定义f[i][j]表示第i行的状态为j时,前i行的方案数,这样一来,本题与“国王”“牧场的安排”很类似,在此不再赘述。

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 #define mod 1000000
 4 #define N 10005
 5 using namespace std;
 6 int n,m,K,ban,ans=0,sta[1005],tot=0,stat,f[N][1005],bit[6],pos;
 7 inline bool check(int x) {
 8     int tmp=0x3f;
 9     for(int i=1; i<=m; ++i) {
10         if(tmp==x%3)return false;
11         tmp=x%3,x/=3;
12     }
13     return true;
14 }
15 inline int read() {
16     int ans=0;
17     char ch=getchar();
18     while(!isdigit(ch))ch=getchar();
19     while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
20     return ans;
21 }
22 inline bool judge(int a,int b) {
23     for(int i=1; i<=m; ++i) {
24         if(a%3==b%3)return false;
25         a/=3,b/=3;
26     }
27     return true;
28 }
29 int main() {
30     n=read(),m=read(),K=read(),stat=1;
31     for(int i=1; i<=m; ++i)stat*=3;
32     for(int i=0; i<stat; ++i)if(check(i))sta[++tot]=i;
33     for(int i=1; i<=m; ++i)ban=ban*3+read()-1;
34     for(int i=1; i<=tot; ++i)if(ban==sta[i]) {
35         pos=i;
36         break;
37     }
38     if(!pos) {
39         puts("0");
40         return 0;
41     }
42     for(int i=1; i<=n; ++i) {
43         if(i==K) {
44             if(i==1)f[i][pos]=1;
45             else for(int j=1; j<=tot; ++j)if(judge(sta[pos],sta[j]))
46                 (f[i][pos]+=f[i-1][j])%=mod;
47         } 
48         else 
49             for(int j=1; j<=tot; ++j) {
50                 if(i==1) f[i][j]=1;
51                 else for(int k=1; k<=tot; ++k) 
52                     if(judge(sta[j],sta[k]))
53                         (f[i][j]+=f[i-1][k])%=mod;
54             }
55     }
56     for(int i=1;i<=tot;++i)(ans+=f[n][i])%=mod;
57     cout<<ans;
58     return 0;
59 }
AC Code

 

posted @ 2019-04-13 20:31  AD_shl  阅读(281)  评论(0编辑  收藏  举报