zerone 01串博弈问题
近日领到了老师的期末作业 其中有这道 01 串博弈问题:
刚开始读题我也是云里雾里 但是精读数遍 “细品” 之后,我发现这是一个 “动态规划” 问题。好嘞,硬着头皮上吧。
分析问题:可知对每个人有两手选择 0 或 1。那么很自然的我们就可以用二叉树来储存每一个选择后的结果。对于本题 ,选择后的结果是还有多少01串未被抹除。所以我再每一个二叉树的节点上再生成一维向量组来保存我们还有那些串未被抹除。这样经过一系列暴力的循环运算后我们将得到一个储存着我们的结果的二叉树。之后的问题是:如何得到必胜方。这一点困扰了我不少时间。不过只要你逻辑清晰还是很容易可以知道:对于每一个节点来说,下一手的选择是对当前的博弈者最有利的选择。比如对亚当来说,选择0,必输,选择1,有可能会嬴,那么亚当绝对会选择1。理清了这个逻辑,加上之前我们已经运算出了博弈的所有结果,这样我们便可以从下往上,从子树反推根代表的必胜者。(这部分可能很绕。。。请多思考),这样我们再建立一个二维向量表,并将刚才所有博弈结果中的胜利者信息(第 i 手,是哪个根的子树)输入进去,然后暴力计算反推:)。虽然我们的方法看起来粗糙 、原始、血腥,任何一个算法老鸟看了都不屑一顾,但能抓住老鼠就是好猫啊!
ps:(之前再网上看过某前辈用的栈+类轻松解决问题,我这个自学c++的小白实在学不来。。。)
下面贴上代码:
// 01串.cpp: 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include<iostream>
#include <vector>
#include <math.h> using namespace std;
void Findwiner(vector<vector<int>>&n, vector<int>&a);
int Findwiner_i(vector<vector<int>>&n, int i);
int p = ;//全局变量 01 串的数量
constexpr auto len = ;//定义01串最大的长度 若31以上要将向量里的 int 换为long int!!!!!! int main()
{
cout << "输入串的数目:";
cin >> p; char a[len];
vector<int> w(p, );
vector<vector<int>> b(p);
for (int i = ; i < p; i++)
{
b[i].resize(len);
}
//将向量全部初始化为3,用来区分01串;
for (int i = ; i < p; i++)
{
for (int j = ; j < len; j++)
{
b[i][j] = ;
} }
//输入字符串 并将其值添加到向量中去。
cout << "初始化:" << endl;
for (int i = ; i < p; i++)
{
cout << "输入第" << i + << "串:";
cin >> a;
for (int j = ; j < len; j++)
{
if (((a[j] - '') == ) || ((a[j] - '') == ))
{
b[i][j] = a[j]-'';
}
else
{
break;
} } }
cout << endl;
cout << "输入为:"<<endl;
for (int i = ; i < p; i++)
{
for (int j = ; j < len; j++)
{
if ((b[i][j] == ) || (b[i][j] == ))
{
cout << b[i][j];
}
else
{
break;
}
}
cout << endl;
} Findwiner(b,w); cout << endl; for (int i = ; i < p; i++)
{
cout << w[i] << " ";
}
cout << endl;
cout << "winer: " << " start " << " end " << endl; cout << endl;
cout << endl;
for (int i = ; i < p; i++)
{
if (w[i] == )
{
if ((i == ) || (w[i - ] == ))
{
cout << "Eva: ";
}
if ((i == ) || (w[i - ] == ))
{
cout << " " << i+ << " ";
}
if (i != p - )
{
if (w[i + ] == )
{
cout << " " << i+ << " " << endl;
}
}
else
{
cout << " " << i+ << " " << endl;
}
}
if (w[i] == )
{
if ((i == ) || (w[i - ] == ))
{
cout << "Adam : ";
}
if ((i == ) || (w[i - ] == ))
{
cout << " " << i+ << " ";
}
if (i != p - )
{
if (w[i + ] == )
{
cout << " " << i+ << " " << endl;
}
}
else
{
cout << " " << i+ << " " << endl;
}
} } system("pause");
return ;
} void Findwiner(vector<vector<int>>&n,vector<int>&a)
{
int i = ; for (i=;i<p;i++)
{
a[i] = Findwiner_i(n,i+);
}
/*a[2] = Findwiner_i(n, 2 + 1);
system("pause");*/ } int Findwiner_i(vector<vector<int>>&n,int i)
{
vector<int> temp(i,);
vector<vector<vector<int>>> dpt(len + );
vector<vector<int>> dp(len + );
int sign1 = , sign2 = , sign3 = , winer = ;
for (int j = ; j < len+; j++)
{
dpt[j].resize(pow(, len + ));
dp[j].resize(pow(, len + ));
}
for (int j = ; j < len+; j++)
{
for (int k = ; k < pow(, len+); k++)
{
dpt[j][k].resize(i);
}
}
for (int j = ; j < i; j++)
{
dpt[][][j] = temp[j];
}
//运行动态规划 计算dpt表 将博弈的结果存在里面
for (int j = ; j < len; j++)
{
for (int k = ; k < pow(,j); k++)
{
for (int l = ; l < i; l++)
{
if (dpt[j][k][l] != )
{
if (n[l][j] == )
{
dpt[j + ][(k + ) * - ][l] = ;
dpt[j + ][(k + ) * - ][l] = dpt[j][k][l];
}
if (n[l][j] == )
{
dpt[j + ][(k + ) * - ][l] = dpt[j][k][l];
dpt[j + ][(k + ) * - ][l] = ;
}
if (n[l][j] == )
{
dpt[j + ][(k + ) * - ][l] = ;
dpt[j + ][(k + ) * - ][l] = ;
}
}
else //dpt[j][k][l]==0;
{
dpt[j + ][(k + ) * -][l] = dpt[j][k][l];
dpt[j + ][(k + ) * - ][l] = dpt[j][k][l];
}
}
}
} //===================================================================
//输出dpt 调试用
/*for (int j = 0; j < len + 1; j++)
{
for (int k = 0; k < pow(2, j ); k++)
{
for (int l = 0; l < i; l++)
{
cout << dpt[j][k][l];
}
cout << " " ;
}
cout << endl;
}*/
//===================================================================
//计算dp dp表表示在二叉树中胜利者的位置 经两次计算将胜利者的代号放入dp[0][0]中
for (int j = ; j <len; j++)
{
for (int k = ; k < pow(, j); k++)
{
sign1 = ;
sign2 = ;
sign3 = ;
for (int l = ; l < i; l++)
{
if (dpt[j][k][l] != )
{
sign1++;
}
if (dpt[j + ][(k + ) * - ][l] != )
{
sign2++;
}
if (dpt[j + ][(k + ) * - ][l] != )
{
sign3++;
}
}
if ((sign1 != )&&(sign2==)&&(sign3==))
{
if (j % == )
{
dp[j][k] = ;
}
if (j % == )
{
dp[j][k] = ;
}
}
}
} //========================================================================
//1 :adam 2:eva
for (int j = len - ; j > ; j--)
{
for (int k = ; k < pow(, j); k++)
{
sign1 = ceil((double)(k + ) / ) - ;
if (sign1 < )
{
sign1 = ;
}
if (dp[j][k] == )
{
if (dp[j - ][sign1] == )
{
dp[j - ][sign1] = dp[j][k];
}
if (dp[j - ][sign1] == )
{
dp[j - ][sign1] = dp[j][k];
}
if (dp[j - ][sign1] == )
{
if (j % == )
{
dp[j - ][sign1] = dp[j][k];
}
if (j % == )
{
dp[j - ][sign1] = dp[j - ][sign1];
} }
} if (dp[j][k] == )
{
if (dp[j - ][sign1] == )
{
dp[j - ][sign1] = dp[j][k];
}
if (dp[j - ][sign1] == )
{
dp[j - ][sign1] = dp[j][k];
}
if (dp[j - ][sign1] == )
{
if (j % == )
{
dp[j - ][sign1] = dp[j][k];
}
if (j % == )
{
dp[j - ][sign1] = dp[j - ][sign1];
} }
} if (dp[j][k] == )
{
dp[j - ][sign1] = dp[j - ][sign1];
}
}
}
//=============================================================
//输出dp 调式用
/* cout << endl << "dp:" << endl;
for (int j = 0; j < len + 1; j++)
{
for(int k=0;k<pow(2,j);k++)
{
cout << dp[j][k] << " ";
}
cout << endl;
}*/
winer = dp[][]; return winer;
}
好了,到此本题结束,代码有点难看,不过凑合能用,希望能帮到以后的学弟学妹吧。:)
zerone 01串博弈问题的更多相关文章
- JZOJ P1847:找01串
传送门 DP预处理+贪心 首先设$f[i][j]$表示长度为$i$的01串中有不大于$j$个1,然后显然 $f[i][j]=\sum_{k=1} ^{j} C[i][k]$ $C[i][j]=C[i- ...
- 洛谷P2727 01串 Stringsobits
P2727 01串 Stringsobits 24通过 55提交 题目提供者该用户不存在 标签USACO 难度普及+/提高 提交 讨论 题解 最新讨论 这题的思路是啥啊!!!跪求- 题目背景 考虑 ...
- C++实现01串排序
题目内容:将01串首先按长度排序,长度相同时,按1的个数从少到多进行排序,1的个数相同时再按ASCII码值排序. 输入描述:输入数据中含有一些01串,01串的长度不大于256个字符. 输出描述:重新排 ...
- 01串(dp)
01串 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 ACM的zyc在研究01串,他知道某一01串的长度,但他想知道不含有“11”子串的这种长度的01串共有多少个, ...
- 【巧妙】【3-21个人赛】Problem C 01串
Problem C Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other) Total Sub ...
- NYOJ-252 01串
01串 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描写叙述 ACM的zyc在研究01串,他知道某一01串的长度,但他想知道不含有"11"子串的这样的长 ...
- NYOJ 252 01串(斐波那契数列变形)
01串 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 ACM的zyc在研究01串,他知道某一01串的长度,但他想知道不含有“11”子串的这种长度的01串共有多少个, ...
- COGS 862. 二进制数01串【dp+经典二分+字符串】
862. 二进制数01串 ★ 输入文件:kimbits.in 输出文件:kimbits.out 简单对比 时间限制:1 s 内存限制:128 MB USACO/kimbits(译 by ...
- 1415: 小ho的01串 [字符串]
点击打开链接 1415: 小ho的01串 [字符串] 题目描述 有一个由0和1组成的字符串,它好长呀--------一望无际 恩,说正题,小ho的数学不太好,虽然是学计算机的但是看见0和1也是很头疼的 ...
随机推荐
- 在WAMP环境下搭建ZendDebugger php调试工具的方法
东西不是新货,所以介绍就不做介绍了,下面主要是配置流程. 首先,下载ZendDebugger,下载链接:http://downloads.zend.com/pdt/server-debugger/,因 ...
- C语言动静态链接库使用(笔记)
看了视频一直没空写........... C静态链接库不用说了跟你写在cpp文件里的函数一样不会有单独的模块 不再赘述生活中用的比较少 例子 .h文件 int Plus(int x, int y); ...
- 吴裕雄--天生自然HADOOP操作实验学习笔记:pvuv统计案例理论
实验目的 复习pv.uv的概念和原理 了解pv.uv的实际意义和获取方法 实验原理 前面我们已经基于mapreduce进行数据的etl处理,实验有很多不足之处,这次实验我们是基于url数据进行pv和u ...
- 吴裕雄--天生自然HADOOP学习笔记:Shell工具使用
实验目的 学习使用xshell工具连接Linux服务器 在连上的服务器中进入用户目录 熟悉简单的文件操作命令 实验原理 熟悉shell命令是熟悉使用linux环境进行开发的第一步,我们在linux的交 ...
- python基础面试题1
Python面试重点(基础篇) 注意:只有必答题部分计算分值,补充题不计算分值. 第一部分 必答题(每题2分) 简述列举了解的编程语言及语言间的区别? c语言是编译型语言,运行速度快,但翻译时间长py ...
- CSS 常用操作
1.对齐 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...
- JS 自动返回每个月的天数
);//M代表月份,可以自己手动设置或者选择 date.setDate() var num = date.getDate(); console.log(num) //输出每个月的天数 var time ...
- Linux centosVMware 磁盘格式化、磁盘挂载、手动增加swap空间
一.磁盘格式化 磁盘分区后不能直接使用,需要对每一个分区格式化,格式化其实就是安装系统文件. 命令mke2fs:不支持格式化成xfs系统文件 mkfs.ext4 == mke2fs -t ext4 ...
- JavaWeb--概述
1.Java Web应用由一组Servlet.HTML页.类以及其他可以被绑定的资源构成.它可以在何种供应商提供的实现Servlet规范的Servlet容器中运行: 2.Java Web应用中包含如下 ...
- 如果不想在django 的settings中保存mysql数据库的密码
如题,你可以编写一个配置文件,用'OPTIONS' 将该配置文件导入进来,这样你发布到git上的源码上就没有你的数据库密码了. 这是django推荐的方法. # settings.py DATABAS ...