hdu 4753 2013南京赛区网络赛 记忆化搜索 ****

看到范围基本可以想到dp了,处理起来有点麻烦

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<algorithm>
  6 #include<map>
  7 #include<queue>
  8 #include<stack>
  9 #include<cmath>
 10 #include<vector>
 11 #define inf 0x3f3f3f3f
 12 #define Inf 0x3FFFFFFFFFFFFFFFLL
 13 #define eps 1e-9
 14 #define pi acos(-1.0)
 15 using namespace std;
 16 typedef long long ll;
 17 //edges[i][j]为边(i,j)的编号,marks[i]表示边i是横边还是竖边
 18 int edges[30][30],marks[30],p[30];
 19 //cont[i]为后添加的边在状态中是多少位,conp[i]为后面的状态中第i位为哪条边
 20 int dp[5000],cont[30],conp[30],len;
 21 //selected[i]表示第i条边是否在最开始已经选了
 22 bool selected[30];
 23 void Init()
 24 {
 25     int cnt=0;
 26     memset(edges,0,sizeof(edges));
 27     memset(marks,0,sizeof(marks));
 28     memset(selected,0,sizeof(selected));
 29     for(int i=0;i<5000;++i) dp[i]=-inf;
 30     for(int i=1;i<=13;i+=4)
 31     {
 32         for(int j=0;j<3;++j)
 33         {
 34             edges[i+j][i+j+1]=edges[i+j+1][i+j]=++cnt;
 35             marks[cnt]=1;
 36         }
 37         if(i==13) break;
 38         for(int j=0;j<4;++j)
 39           edges[i+j][i+j+4]=edges[i+j+4][i+j]=++cnt;
 40     }
 41     for(int i=0;i<30;++i) p[i]=1<<i;
 42 }
 43 inline bool check(int a,int b,int c,int state)
 44 {
 45     if(!selected[a]&&(p[cont[a]]&state)==0) return false;
 46     if(!selected[b]&&(p[cont[b]]&state)==0) return false;
 47     if(!selected[c]&&(p[cont[c]]&state)==0) return false;
 48     return true;
 49 }
 50 int getpoints(int e,int now)
 51 {
 52     int sum=0;
 53     int a,b,c;
 54     if(marks[e])
 55     {
 56         a=e-4;b=e-3;c=e-7;
 57         if(c>0&&check(a,b,c,now))
 58           sum++;
 59         a=e+3;b=e+4;c=e+7;
 60         if(a<24&&check(a,b,c,now))
 61           sum++;
 62     }
 63     else
 64     {
 65         a=e-4;b=e-1;c=e+3;
 66         if(marks[c]&&check(a,b,c,now))
 67           sum++;
 68         a=e-3;b=e+1;c=e+4;
 69         if(marks[a]&&check(a,b,c,now))
 70           sum++;
 71     }
 72     return sum;
 73 }
 74 int f(int state)
 75 {
 76     if(state==p[len]-1) return 0;
 77     if(dp[state]!=-inf) return dp[state];
 78     dp[state]=0;
 79     int tmp=-inf;
 80     for(int i=0;i<len;++i)
 81     {
 82         if((p[i]&state)==0)
 83           tmp=max(tmp,getpoints(conp[i],state)-f(p[i]|state));
 84     }
 85     return dp[state]=tmp;
 86 }
 87 int main()
 88 {
 89     //freopen("in.txt","r",stdin);
 90     //freopen("out.txt","w",stdout);
 91     int t,tcase=0;
 92     scanf("%d",&t);
 93     while(t--)
 94     {
 95         tcase++;
 96         Init();
 97         int n,a,b,e,ans=0,turns=0;
 98         scanf("%d",&n);
 99         len=24-n;
100         for(int i=0;i<n;++i)
101         {
102             scanf("%d%d",&a,&b);
103             e=edges[a][b];
104             if(turns)
105               ans-=getpoints(e,0);
106             else ans+=getpoints(e,0);
107             turns^=1;
108             selected[e]=true;
109         }
110         int cnt=0;
111         for(int i=1;i<=24;++i)
112           if(!selected[i]) {conp[cnt]=i;cont[i]=cnt;cnt++;}
113         if(turns)
114           ans-=f(0);
115         else ans+=f(0);
116         printf("Case #%d: ",tcase);
117         if(ans>0) puts("Tom200");
118         else puts("Jerry404");
119     }
120     return 0;
121 }
原文地址:https://www.cnblogs.com/cnblogs321114287/p/4774444.html