洛谷P4363 一双木棋 chess

洛谷P4363 一双木棋 chess

省选最水的一道题了。

且看我数个月AC一道题......

具体是这样的:
我们发现这个下了棋的地方一定形成一个锯齿形,那么怎么状态压缩呢?

维护轮廓线!

从左下角出发,向上为1,向右为0即可。

然后我们就开心的DP…等等
这按照什么顺序DP啊!!
好,那么我们退而求次,记忆化搜索!
然后就没有然后了…

需要注意的地方:

  • 记得判断max还是min
  • 二进制位运算一如既往的烦人
  • DFS起点和终点的处理
  • 求最大差值,转化为加A减B即可

那么我们调了一年后终于A了!!

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int N = 11,INF = 0x7f7f7f7f;
 5 int m,n,mp[1<<21],A[N][N],B[N][N],aim;
 6 
 7 bool who(int sta) { //判断该谁走的函数
 8     int p=m,ans=0;
 9     while(sta) {
10         if(sta&1) {
11             ans+=p;
12         }
13         else {
14             p--;
15         }
16         sta=sta>>1;
17     }
18     return !(ans&1);
19 }
20 
21 void out(int sta) { //输出这个状态(二进制) 
22     int t[300],T=0;
23     fill(t,t+30,0);
24     while(sta) {
25         t[++T] = bool(sta&1);
26         sta=sta>>1;
27     }
28     printf(" ");
29     for(int i=m+n;i>=1;i--) {
30         printf("%d",t[i]);
31     }
32     printf(" ");
33     return;
34 }
35 
36 int DFS(int now) {
37 
38     ///printf("DFS\n");
39 
40     if(mp[now]) { // 记忆化
41         return mp[now];
42     }
43     if(now==aim) {
44         return 0;
45     }
46 
47     bool f = who(now);
48     int p=0,ans=(f?(-INF):INF);
49     for(int i=0;i<m+n;i++) {
50         if(now&(1<<i)) {
51             p++;
52         }                          // gay
53         if((!(now&(1<<i)))&&(now&(1<<(i+1))))  { /* 10 */ /** 10 */  /// [p+1][m+p-i]
54             int nextsta = (now|(1<<i))&(~(1<<(i+1)));
55             int x=p+1;
56             int y=m+p-i;
57             if(f) {
58                 ans=max(ans,DFS(nextsta)+A[x][y]);
59             }
60             else {
61                 ans=min(ans,DFS(nextsta)-B[x][y]);
62             }
63         }
64     }
65     mp[now]=ans;
66     //printf("DFS:");
67     //out(now);
68     //printf("\n");
69     return ans;
70 }
71 
72 int main(){
73     scanf("%d%d",&n,&m);
74     for(int i=1;i<=n;i++) {
75         for(int j=1;j<=m;j++) {
76             scanf("%d",&A[i][j]);
77         }
78     }
79     for(int i=1;i<=n;i++) {
80         for(int j=1;j<=m;j++) {
81             scanf("%d",&B[i][j]);
82         }
83     }
84     int s=0; // 起点
85     for(int i=1;i<=n;i++) {
86         aim=aim<<1|1; // 终点
87         s=s<<1|1;
88     }
89     for(int i=1;i<=m;i++) {
90         s=s<<1;
91     }
92 
93     printf("%d",DFS(s));
94 
95     return 0;
96 }
AC代码

 

posted @ 2018-05-05 17:44  garage  阅读(175)  评论(0编辑  收藏  举报