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 }
时间: 2024-10-15 00:47:42

hdu 4753 2013南京赛区网络赛 记忆化搜索 ****的相关文章

hdu 4751 2013南京赛区网络赛 二分图判断 **

和以前做过的一个二分图颇为相似,以前的是互相不认识的放在一组,这个是互相认识的,本质上是相同的 是 hdu 2444 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace st

hdu 4738 2013杭州赛区网络赛 桥+重边+连通判断 ***

题意:有n座岛和m条桥,每条桥上有w个兵守着,现在要派不少于守桥的士兵数的人去炸桥,只能炸一条桥,使得这n座岛不连通,求最少要派多少人去. 处理重边 边在遍历的时候,第一个返回的一定是之前去的边,所以这条边忽略,然后继续遍历,此时可以通过未遍历的边返回pre 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath

hdu 4741 2013杭州赛区网络赛 dfs ***

起点忘记录了,一直wa 代码写的很整齐,看着很爽 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 con

hdu 4628 Pieces(状态压缩+记忆化搜索)

Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1811    Accepted Submission(s): 932 Problem Description You heart broke into pieces.My string broke into pieces.But you will recover one

hdu 1078 FatMouse and Cheese(简单记忆化搜索)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1078 题意:给出n*n的格子,每个各自里面有些食物,问一只老鼠每次走最多k步所能吃到的最多的食物 一道简单的记忆化搜索题,从起点开始搜索即可没什么问题,可以拿来练练手. #include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std

HDU 4960 Another OCD Patient(区间dp记忆化搜索)

题目大意:给你一串数字让你判断经过若干次合并,使得这个数字串变成回文串的最小成本是多少.第一行是数字串,第二行是合并连续i个数字的成本是多少. 解题思路:区间dp,可以进行记忆化搜索,如果左边比右边和大那么右边一定是小了,右边比左边大那么左边一定小了.因为保证有解.具体不太好说,直接看代码吧. Another OCD Patient Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe

HDU 1248寒冰王座-全然背包或记忆化搜索

寒冰王座 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13001    Accepted Submission(s): 6620 Problem Description 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,仅仅有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前. 死亡骑

hdu 1078 FatMouse and Cheese (dfs+记忆化搜索)

pid=1078">FatMouse and Cheese Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4811    Accepted Submission(s): 1945 Problem Description FatMouse has stored some cheese in a city. The city can

hdu 1978 How many ways (动态规划、记忆化搜索)

How many ways Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2957    Accepted Submission(s): 1733 Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下: 1.机器人一开始在棋盘的起始点并