HDU4753 Fishhead’s Little Game——2013 ACM/ICPC Asia Regional Nanjing Online
今天比赛又是做得好水的。被狂虐啊。
比赛两个多小时一直没出题,遒遒最先交的若干发都wa了。T_T
我独自在一遍苦思了1006这个题,还好最后把这个题目A掉了,不然又是深坑队友。
题目的意思我就不多说了,直接去hdu上看题意,题意很容易懂。
这里说一下我的解题思路吧。
首先题目总共有24条边这是不会变得,但是每次刚开始的一些条件是作为已知条件给你的,所以你不用考虑读数时候游戏者的智商问题。
对于已知的步奏,我们只要模拟,并且记录两个人的得分就可以了。
关键是后面怎么去处理呢?
其实这个题目有一个关键的条件,虽然总边数有24,但是未知的边数只有12,12是个很小的数字,于是总共可能的状态数只有2^12个,可以用状态压缩dp搞定啦。
但是这个题目还涉及到一些博弈论的知识,简单的说一下吧!
首先说明两个名词,必胜态和必败态。顾名思义,名词我就不解释了。
接下来就是怎么判断一个状态是否必胜态或者必败态。(会不会有中间态?显然不会,不解释)
当前状态是必胜态,当且仅当存在它的某一个下一步状态为必败态;当前状态是必败态,当且仅当它的所有的下一步状态全部都是必胜态。
好好理解上一步这句话。
这个题目需要我们记录的可不仅仅是必胜还是必败,还要我们每个状态记录到底是胜了多少分还是败了多少分?有了这里我们就可以dp了。
我们用一个数组(我在代码中用的是ans1[x])来记录x状态先手的人以最优策略能够胜对方多少分。
用二进制(最多12个0)表示初始状态,即所有的地方都没有填成实线。
显然最终的状态(也就是全部为1的时候,111111……)其所对应的ans1的值为0,因为可以理解为最终都取完了,两个人都不取了,所以差值为0,
于是我们倒推,从1多的数推向1少的数,最终算出0,也就是当前这个人以最优策略能够胜对方多少分!(不用记录每个人的得分,因为得分高并比一定是最优解)
下面我稍微指出来题目的几个小坑吧,都是泪堆出来的惨痛教训!
1.前一段读数的时候要把放过的边全部存起来,同时还要统计两个人的分别得分。
2.虽然游戏从一开始的时候是Tom200开始填充实线的,但是如果读数的时候n为奇数说明dp的时候是Jerry404第一个开始填充的(这里特别要注意)
3.这也不算是坑吧,就是要建立起两点与边的对应关系,同时还要给边编号,dp的每一位是表示的边的状态,不是点哦。
下面上我的代码(巨挫),比赛的时候写的,很难看,请谅解。(中间有两个函数功能其实是一样的,是我写挫了)
如果觉得太难看,我觉得我上面讲得已经十分明白了,自己直接写吧。我的太难看了。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; int f1[],f2[],a[][],p[],q[],t,n,x,y,ans[],ans1[],ans2[]; void codeit()
{
int N=;
for (int i=; i<; i++)
{
if (i%==) continue;
a[i][i+]=++N;
}
for (int i=; i<=; i++) a[i][i+]=++N;
f1[]=,f1[]=,f1[]=;
f1[]=,f1[]=,f1[]=;
f1[]=,f1[]=,f1[]=;
for (int i=; i<=; i++) f1[f1[i]]=i;
} void add(int& ANS,int now)
{
int pp[],pre=;
memset(pp,-,sizeof pp);
for (int i=; i<=; i++) pp[i]=p[i];
if (now<=)
{
if (now>=)
{
now-=;
if (pp[f1[now]]== && pp[f1[now]+]== && pp[now]==) pre++;
}
else
{
if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
if (now>)
{
now-=;
if (pp[f1[now]]== && pp[f1[now]+]== && pp[now]==) pre++;
}
}
}
else
{
if (now%==)
{
if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
}
else
{
if (now%!=)
{
if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
}
now--;
if (pp[now]== && pp[f1[now]]== && pp[f1[now]+]==) pre++;
}
}
ANS+=pre;
} int count(int cur,int now)//在cur的状态下加入第now条边
{
//cout<<"now add: "<<cur<<' '<<now<<endl;
int pp[],pre=;
memset(pp,-,sizeof pp);
for (int i=; i<=; i++) if (p[i]==) pp[i]=;
for (int i=; i<=n; i++) { if ((cur&(<<(i-)))) pp[q[i]]=; /*cout<<q[i]<<" q[i] \n";*/ }
//for (int i=1; i<=24; i++) if (pp[i]==0) cout<<i<<' '; else cout<<0<<' '; cout<<endl;
now=q[now]; //cout<<"adding : "<<now<<endl;
if (now<=)
{
if (now>=)
{
now-=;
if (pp[f1[now]]== && pp[f1[now]+]== && pp[now]==) pre++;
}
else
{
if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
if (now>)
{
now-=;
if (pp[f1[now]]== && pp[f1[now]+]== && pp[now]==) pre++;
}
}
}
else
{
if (now%==)
{
if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
}
else
{
if (now%!=)
{
if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
}
now--;
if (pp[now]== && pp[f1[now]]== && pp[f1[now]+]==) pre++;
}
}
return pre;
} int main()
{
int cas=;
codeit();
scanf("%d",&t);
while (t--)
{
int tot,tep;
memset(p,-,sizeof p);
memset(ans,,sizeof ans);
memset(q,,sizeof q);
scanf("%d",&n);
for (int i=; i<=n; i++)
{
scanf("%d%d",&x,&y);
if (x>y) swap(x,y);
add(ans[i%],a[x][y]);
p[a[x][y]]=;
}
int N=;
for (int i=; i<=; i++)
{
if (p[i]==-) q[++N]=i;
}
/*for (int i=1; i<=24; i++)
if (q[i]>0) cout<<i<<" : "<<q[i]<<endl; cout<<"q[i] \n";*/
n=-n;
tot=(<<n)-;
for (int i=; i<tot; i++) ans1[i]=-;
ans1[tot]=;
for (int i=tot; i>=; i--)
{
for (int j=; j<=n; j++)
{
if ((i&(<<(j-)))==)
{
tep=count(i,j);
int next=i|(<<(j-));
if (tep-ans1[next]>ans1[i]) ans1[i]=tep-ans1[next];
}
}
}
/*for (int i=1; i<=10; i++) cout<<ans1[i]<<' '; cout<<endl;*/
if (n%==) ans1[]=-ans1[];
if (ans[]+ans1[]>ans[]) printf("Case #%d: Tom200\n",++cas);
else printf("Case #%d: Jerry404\n",++cas);
}
return;
}
HDU4753 Fishhead’s Little Game——2013 ACM/ICPC Asia Regional Nanjing Online的更多相关文章
- HDU 4749 Parade Show 2013 ACM/ICPC Asia Regional Nanjing Online
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4749 题目大意:给一个原序列N,再给出一个序列M,问从N中一共可以找出多少个长度为m的序列,序列中的数 ...
- [2013 ACM/ICPC Asia Regional Nanjing Online C][hdu 4750]Count The Pairs(kruskal + 二分)
http://acm.hdu.edu.cn/showproblem.php?pid=4750 题意: 定义f(u,v)为u到v每条路径上的最大边的最小值..现在有一些询问..问f(u,v)>=t ...
- HDU 4751 Divide Groups 2013 ACM/ICPC Asia Regional Nanjing Online
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4751 题目大意:判断一堆人能否分成两组,组内人都互相认识. 解题思路:如果两个人不是相互认识,该两人之 ...
- hdu 4751 Divide Groups bfs (2013 ACM/ICPC Asia Regional Nanjing Online 1004)
SDUST的训练赛 当时死磕这个水题3个小时,也无心去搞其他的 按照题意,转换成无向图,预处理去掉单向的边,然后判断剩下的图能否构成两个无向完全图(ps一个完全图也行或是一个完全图+一个孤点) 代码是 ...
- HDU 4758——Walk Through Squares——2013 ACM/ICPC Asia Regional Nanjing Online
与其说这是一次重温AC自动机+dp,倒不如说这是个坑,而且把队友给深坑了. 这个题目都没A得出来,我只觉得我以前的AC自动机的题目都白刷了——深坑啊. 题目的意思是给你两个串,每个串只含有R或者D,要 ...
- HDU 4757 Tree(可持久化字典树)(2013 ACM/ICPC Asia Regional Nanjing Online)
Problem Description Zero and One are good friends who always have fun with each other. This time, ...
- hduoj 4710 Balls Rearrangement 2013 ACM/ICPC Asia Regional Online —— Warmup
http://acm.hdu.edu.cn/showproblem.php?pid=4710 Balls Rearrangement Time Limit: 6000/3000 MS (Java/Ot ...
- hduoj 4708 Rotation Lock Puzzle 2013 ACM/ICPC Asia Regional Online —— Warmup
http://acm.hdu.edu.cn/showproblem.php?pid=4708 Rotation Lock Puzzle Time Limit: 2000/1000 MS (Java/O ...
- hduoj 4715 Difference Between Primes 2013 ACM/ICPC Asia Regional Online —— Warmup
http://acm.hdu.edu.cn/showproblem.php?pid=4715 Difference Between Primes Time Limit: 2000/1000 MS (J ...
随机推荐
- 20155337祁家伟 2016-2017-2 《Java程序设计》第2周学习总结
20155337 2016-2017-2 <Java程序设计>第2周学习总结 教材学习内容总结 这周我学习了从JDK到IDE的学习内容,简单来说分为以下几个部分 使用命令行和IDE两种方式 ...
- 考研编程练习---StringMatching(后缀表达式)
题目描述: Finding all occurrences of a pattern in a text is a problem that arises frequently in text-edi ...
- 【原创】user.id字段
odoo中User.ID 字段是用户登录表 res_users 中的字段,所以要关联某个用户或是判断某个用户,可以利用该字段. 例如:在某个 界面中的domain中,要求显示的是关联某用户的单子,则如 ...
- [agc003F]Fraction of Fractal
Description 传送门 Solution 本篇博客思路来自大佬的博客(侵删). 我们定义如果网格的第一行和最后一行的第i列都为黑色,则它是一个上下界接口.左右界接口定义同上. 如果上下界接口和 ...
- php 批量载入文件的几种方式
方式1:spl_autoload_register // Register the autoloader. /** * Contains the functionality for auto-load ...
- 数据库表,id自动递增重置,从1开始
问题: 删除数据表的数据后,发现下次插入数据,主键id并没有重置,还是在原来基础上继续增加 解决: ; TRUNCATE table table_name; ; 参考: https://stackov ...
- JavaFX学习笔记——ControlsFX控件集学习——ToggleSwitch和BreadCrumbBar例子
ToggleSwitch ToggleSwitch ts = new ToggleSwitch("开"); 效果 BreadCrumbBar BreadCrumbBar<St ...
- idea 模版之自定义类与方法注释
idea 模版之自定义类与方法注释 很多公司都有要求的代码注释规范,我们每新建类或者方法的时候从新复制粘贴很麻烦,而且容易粘错. 当然自定义模板还可以用到很多地方,比如系统自带的 sout就是syst ...
- C语言--指针详解
这段时间在看 Linux 内核,深觉 C 语言功底不扎实,很多代码都看不太懂,深入学习巩固 C 语言的知识很有必要.先从指针开始. 一.什么是指针 C语言里,变量存放在内存中,而内存其实就是一组有序字 ...
- Linux内核学习笔记(1)-- 进程管理概述
一.进程与线程 进程是处于执行期的程序,但是并不仅仅局限于一段可执行程序代码.通常,进程还要包含其他资源,像打开的文件,挂起的信号,内核内部数据,处理器状态,一个或多个具有内存映射的内存地址空间及一个 ...