pku1332 Finding Liars DP 经典好题

题意:
i (tester) j (testee)/td> test outcome ai,j
truth-teller truth-teller 0
truth-teller liar 1
liar truth-teller 0 or 1
liar liar 0 or 1


 

不用说了吧

解法:
这题我开始往2-sat的方向去想,搞死了搞不出来,今天洗澡的时候忽然发现。。这题原来是一个水了不能再水的DP
首先,设置DP状态(pos,left,jud),即决策到第pos个人时还允许有left个人是骗子,并且第pos个人是诚实的/骗子时的状态。
状态是一个集合,我用的bitset。
关于状态转移就很简单了
分2种情况:
1、第pos个人是骗子,那么第pos+1个人是诚实的或者骗子都可以
2、第pos个人是诚实的,那么第pos+1个人只能根据第pos个人说的话来决定
第一个人的情况要枚举,并且最后特别判断下
还有就是,集合初始化为全1,然后状态的运算是与运算。注意滚动数组,不然MLE到你哭~

代码:
 1# include <cstdio>
 2# include <cstring>
 3# include <bitset>
 4using namespace std;
 5# define N 1005
 6bitset<N> dp[2][N][2],one,zero;
 7int data[N],n,maxnum;
 8int main()
 9{
10    int test;
11    scanf("%d",&test);
12    one.set();
13    zero.reset();
14    while(test--)
15    {
16        one.set();
17        zero.reset();
18        scanf("%d%d",&n,&maxnum);
19        for(int i=0;i<n;i++)
20            scanf("%d",data+i);
21        bitset<N> res=one;
22        for(int i=0;i<=maxnum;i++)
23            dp[0][i][0]=zero,dp[0][i][1]=one;
24        for(int i=1;i<=n;i++)
25        {
26            for(int j=0;j<=maxnum;j++)
27                dp[i%2][j][0]=dp[i%2][j][1]=one;
28            for(int j=0;j<=maxnum;j++)
29                dp[i%2][j][0]&=dp[(i-1)%2][j][1];
30            for(int j=0;j<maxnum;j++)
31                dp[i%2][j][1]&=dp[(i-1)%2][j+1][1].set(i);
32            if(!data[i-1])
33                for(int j=0;j<=maxnum;j++)
34                    dp[i%2][j][0]&=dp[(i-1)%2][j][0];
35            else
36                for(int j=0;j<maxnum;j++)
37                    dp[i%2][j][1]&=dp[(i-1)%2][j+1][0].set(i);
38        }

39        for(int i=0;i<=maxnum;i++)
40            res&=dp[n%2][i][0];
41
42        for(int i=0;i<maxnum;i++)
43            dp[0][i][0]=one,dp[0][i][1]=zero.set(0);
44        dp[0][maxnum][0]=dp[0][maxnum][1]=one;
45        for(int i=1;i<=n;i++)
46        {
47            for(int j=0;j<=maxnum;j++)
48                dp[i%2][j][0]=dp[i%2][j][1]=one;
49            for(int j=0;j<=maxnum;j++)
50                dp[i%2][j][0]&=dp[(i-1)%2][j][1];
51            for(int j=0;j<maxnum;j++)
52                dp[i%2][j][1]&=dp[(i-1)%2][j+1][1].set(i);
53            if(!data[i-1])
54                for(int j=0;j<=maxnum;j++)
55                    dp[i%2][j][0]&=dp[(i-1)%2][j][0];
56            else
57                for(int j=0;j<maxnum;j++)
58                    dp[i%2][j][1]&=dp[(i-1)%2][j+1][0].set(i);
59        }

60        for(int i=0;i<maxnum;i++)
61            res&=dp[n%2][i][1];
62
63
64        if(res.count()==0) printf("0 0\n");
65        else
66        {
67            int pos=-1;
68            for(int i=0;i<n&&pos==-1;i++)
69                if(res[i])
70                    pos=i;
71            printf("%d %d\n",res.count(),pos+1);
72        }

73    }

74    return 0;
75}

posted on 2011-01-24 01:01 yzhw 阅读(406) 评论(0)  编辑 收藏 引用 所属分类: DP


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年10月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

导航

统计

公告

统计系统

留言簿(1)

随笔分类(227)

文章分类(2)

OJ

最新随笔

搜索

积分与排名

最新评论

阅读排行榜