numdle
算一下信息熵,每次取最大的询问。
复杂度 O(n^2),常数略大。
好像还可以组合计数,但懒得想了。
#include<iostream>
#include<vector>
#include<string>
#include<cmath>
#pragma GCC optimize("Ofast")
using namespace std;
vector<string> now;
bool multi=0;
void init(bool tag){
now.clear();
for(char a='0';a<='9';a++)
for(char b='0';b<='9';b++)
for(char c='0';c<='9';c++)
for(char d='0';d<='9';d++){
string x="";
x+=a; x+=b; x+=c; x+=d;
if(tag||(a!=b&&a!=c&&a!=d&&b!=c&&b!=d&&c!=d))
now.push_back(x);
}
}
void check(const string &A,const string &B,int &x,int &y){
static int b[10]; x=y=0;
for(int i=0;i<10;i++) b[i]=0;
for(int i=0;i<4;i++) b[A[i]-'0']++;
for(int i=0;i<4;i++)
if(A[i]==B[i]) x++;
else y+=(b[B[i]-'0']>0);
}
int update(vector<string> &V,int x,int y,const string &g,bool op=0){
if(!op){
vector<string> w; w.clear();
int x_,y_;
for(string v:V){
check(v,g,x_,y_);
if(x_==x&&y_==y) w.push_back(v);
}
return V=w,0;
}else{
int x_,y_,ret=0;
for(string v:V){
check(v,g,x_,y_);
if(x_==x&&y_==y) ret++;
}
return ret;
}
}
string nq(vector<string> &V){
double mx=0; string gu=V[0];
int mp[5][5];
for(string g:V){
double e=0;
for(int x=0;x<=4;x++)
for(int y=0;y<=4;y++)
mp[x][y]=update(V,x,y,g,1);
for(string v:V){
int x,y; check(v,g,x,y);
if(mp[x][y]) e+=log2(1.0*V.size()/mp[x][y]);
}
if(e>mx) mx=e,gu=g;
}
return gu;
}
string Add_;
int main(){
Point_4:
cout<<"type : ";
cin>>multi;
cin.ignore();
init(multi);
string rq="0123";
int x,y;
while(now.size()!=1){
cout<<rq<<endl;
Point_1:
getline(cin,Add_);
if(Add_[0]=='F') goto Point_4;
if(Add_[0]=='P'){
for(auto x:now)
cout<<x<<" ";
cout<<endl;
goto Point_1;
}
if(Add_[0]=='D'){
printf("E=%.3lf\n",log2(now.size()));
goto Point_1;
}
if(Add_[0]=='A'){
Point_2:
getline(cin,Add_);
if(Add_[0]=='Q')
goto Point_3;
rq=Add_.substr(0,4);
x=Add_[5]-'0';
y=Add_[7]-'0';
update(now,x,y,rq);
goto Point_2;
}
x=Add_[0]-'0';
y=Add_[2]-'0';
update(now,x,y,rq);
Point_3:
if(now.size()==1) break;
rq=nq(now);
}
cout<<rq<<"!!!"<<endl;
}