Testing Round #13 C. Interactive Bulls and Cows (Hard) 枚举
2017-01-11 02:19
225 查看
题意:给定一个隐藏0-9组成的各个位置不同的4位字符串。每次猜测一个数字,系统返回bulls:位置对且值对的数字的个数;cows:位置不对但是值对的个数,且多个值对算一个。如:1234 与 2222 bulls=1,cows=0。
总共有5040种可能,每次猜测的时候:
1.尝试5040种中每一种可能,使得在当前可能的答案中,返回的bulls和cows的数量的最坏的情况最小。即每次保证排除足够多的答案。
2.更新当前的可行答案。即将可行答案与猜测的4位数比对bulls与cows,若与系统返回值不同,则不可能是正确答案。
直至系统返回4 0退出。
代码中:v1代表可行答案,v2表示5040种合法字符串。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned int uii;
const int inf=0x3f3f3f3f;
int n1,n2,cnt[5][5],t2,tr,c,b;
vector<string> v1,v2,v3;
set<char> stc;
set<string> st;
string str;
char s[5];
bool v[10];
void pre() {
for (int i=123;i<=9999;++i) {
stc.clear();
s[3]=i%10+'0';
s[2]=i/10%10+'0';
s[1]=i/100%10+'0';
s[0]=i/1000%10+'0';
for (int j=0;j<4;++j)
stc.insert(s[j]);
if (stc.size()==4) {
v1.push_back(s);
v2.push_back(s);
}
}
}
bool fb() {
st.clear();
for (uii i=0;i<v1.size();++i)
st.insert(v1[i]);
t2=inf;
for (uii i=0;i<v2.size();++i) {
tr=0;
memset(v,0,sizeof v);
memset(cnt,0,sizeof cnt);
for (int j=0;j<4;++j)
v[v2[i][j]-'0']=1;
for (uii j=0;j<v1.size();++j) {
n1=n2=0;
for (int k=0;k<4;++k) {
if (v[v1[j][k]-'0'])
++n2;
if (v1[j][k]==v2[i][k])
++n1;
}
n2-=n1;
++cnt[n1][n2];
}
for (int j=0;j<=4;++j)
for (int k=0;k<=4;++k)
tr=max(tr,cnt[j][k]);
if (t2>tr) {
t2=tr;
str=v2[i];
} else if (t2==tr&&st.find(v2[i])!=st.end())
str=v2[i];
}
cout<<str<<endl;
fflush(stdout);
scanf("%d%d",&b,&c);
if (b==4)
return false;
v3.clear();
memset(v,0,sizeof v);
for (int j=0;j<4;++j)
v[str[j]-'0']=1;
for (uii j=0;j<v1.size();++j) {
n1=n2=0;
for (int k=0;k<4;++k) {
if (v[v1[j][k]-'0'])
++n2;
if (v1[j][k]==str[k])
++n1;
}
n2-=n1;
if (n1==b&&n2==c)
v3.push_back(v1[j]);
}
v1=v3;
return true;
}
int main()
{
pre();
while (fb()) {}
return 0;
}
总共有5040种可能,每次猜测的时候:
1.尝试5040种中每一种可能,使得在当前可能的答案中,返回的bulls和cows的数量的最坏的情况最小。即每次保证排除足够多的答案。
2.更新当前的可行答案。即将可行答案与猜测的4位数比对bulls与cows,若与系统返回值不同,则不可能是正确答案。
直至系统返回4 0退出。
代码中:v1代表可行答案,v2表示5040种合法字符串。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned int uii;
const int inf=0x3f3f3f3f;
int n1,n2,cnt[5][5],t2,tr,c,b;
vector<string> v1,v2,v3;
set<char> stc;
set<string> st;
string str;
char s[5];
bool v[10];
void pre() {
for (int i=123;i<=9999;++i) {
stc.clear();
s[3]=i%10+'0';
s[2]=i/10%10+'0';
s[1]=i/100%10+'0';
s[0]=i/1000%10+'0';
for (int j=0;j<4;++j)
stc.insert(s[j]);
if (stc.size()==4) {
v1.push_back(s);
v2.push_back(s);
}
}
}
bool fb() {
st.clear();
for (uii i=0;i<v1.size();++i)
st.insert(v1[i]);
t2=inf;
for (uii i=0;i<v2.size();++i) {
tr=0;
memset(v,0,sizeof v);
memset(cnt,0,sizeof cnt);
for (int j=0;j<4;++j)
v[v2[i][j]-'0']=1;
for (uii j=0;j<v1.size();++j) {
n1=n2=0;
for (int k=0;k<4;++k) {
if (v[v1[j][k]-'0'])
++n2;
if (v1[j][k]==v2[i][k])
++n1;
}
n2-=n1;
++cnt[n1][n2];
}
for (int j=0;j<=4;++j)
for (int k=0;k<=4;++k)
tr=max(tr,cnt[j][k]);
if (t2>tr) {
t2=tr;
str=v2[i];
} else if (t2==tr&&st.find(v2[i])!=st.end())
str=v2[i];
}
cout<<str<<endl;
fflush(stdout);
scanf("%d%d",&b,&c);
if (b==4)
return false;
v3.clear();
memset(v,0,sizeof v);
for (int j=0;j<4;++j)
v[str[j]-'0']=1;
for (uii j=0;j<v1.size();++j) {
n1=n2=0;
for (int k=0;k<4;++k) {
if (v[v1[j][k]-'0'])
++n2;
if (v1[j][k]==str[k])
++n1;
}
n2-=n1;
if (n1==b&&n2==c)
v3.push_back(v1[j]);
}
v1=v3;
return true;
}
int main()
{
pre();
while (fb()) {}
return 0;
}
相关文章推荐
- c程序第三篇3
- 如何获取Azure AD tenant的tenant Id?
- Linux高级文本处理之gawk内置变量(二)
- Netty实践(二):TCP拆包、粘包问题
- Android开发——单击事件和长按事件
- ORACLE 误删表、误删表数据后恢复
- javascript基础
- Vue学习笔记(1) 一开始的使用以及Vue实例的详解
- c程序第二篇2
- 浅谈动感歌词-歌词生成篇
- jquery 调用 click 事件 的 三种 方式
- javaScript之DOM操作(一)
- 人脸识别常用库和API
- 关于Anaconda下载慢的解决方法
- 数学+精度 hpu 1207: 杨八方的问题
- c程序第一篇1
- codeforces 509E Pretty Song [递推]【杂类】
- Volley请求中,使用cookit进行服务器与客户端的会话保持
- C编程练习题(待解决)
- mysql补充(3)优化sql语句查询常用的30种方法