Testing Round #13 C. Interactive Bulls and Cows (Hard) 枚举

题意:给定一个隐藏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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值