题目链接:http://codeforces.com/problemset/problem/442/A
题目大意:给你n张卡片,你知道这n张卡片都是什么,但是不知道他们的位置。你每次可以请求朋友指出一种颜色的卡片,或者一种数字的卡片。问你最少需要多少次能够知道每个卡片的位置。
首先,如果其他所有卡片都知道了,最后一张卡片不需要指示就知道了。
然后我们枚举哪张是最后一张卡片。
将五种颜色放在x轴,5个数字放在y轴。
一次询问就是画一条线,先去掉交叉点,再看剩下的点是不是唯一在一条直线里。
bitmask,一共最多25条线。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <cmath>
#include <numeric>
#include <iterator>
#include <iostream>
#include <cstdlib>
#include <functional>
#include <queue>
#include <stack>
#include <string>
#include <cctype>
using namespace std;
#define PB push_back
#define MP make_pair
#define SZ size()
#define ST begin()
#define ED end()
#define CLR clear()
#define ZERO(x) memset((x),0,sizeof(x))
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
const double EPS = 1e-; struct POINT{
int x,y;
int hash,idx;
}; int n,tot;
vector<POINT> pts;
set<int> se;
vector<POINT> vx[],vy[]; POINT GetPoint(const char* buf){
POINT res;
if( buf[] == 'R' ) res.x = ;
else if( buf[] =='G' ) res.x = ;
else if( buf[] == 'B' ) res.x = ;
else if( buf[] == 'Y' ) res.x = ;
else if( buf[] == 'W' ) res.x = ;
res.y = buf[] -'';
res.hash = res.x*+res.y;
return res;
} void SplitPoints() {
for(int i=;i<pts.size();i++){
POINT &pt = pts[i];
vx[pt.x].PB(pt);
vy[pt.y].PB(pt); // printf("vx[%d].PB(%d)\n",pt.x,pt.idx);
// printf("vy[%d].PB(%d)\n",pt.y,pt.idx);
}
} bool check(int mask,int out) { int vis[];
for(int i=;i<;i++) vis[i] = ; for( int i=;i<;i++ ){
if( (mask>>i)& ) {
int now = i+;
if(now<=) {
if( vx[now].size()== ) return false;
} else {
now -= ;
if( vy[now].size()== ) return false;
}
}
} // if(mask==261) puts("****"); for( int i=;i<;i++ ) {
if( (mask>>i)& ) {
int now = i+;
// if(mask==261) printf("now i=%d\n",now);
if( now<= ) {
for(int j=;j<vx[now].size();j++){
if( vis[vx[now][j].idx] == ) continue;
vis[vx[now][j].idx]++;
}
} else {
now -= ;
for(int j=;j<vy[now].size();j++){
if( vis[vy[now][j].idx]== ) continue;
vis[vy[now][j].idx]++;
}
}
}
} for(int i=;i<;i++){
if( (mask>>i)& ) {
int now = i+;
if( now<= ) {
// x
int cnt = ;
for(int j=;j<vx[now].size();j++) if(vis[vx[now][j].idx]<) cnt++;
if( cnt== ) {
for(int j=;j<vx[now].size();j++) if( vis[vx[now][j].idx] < )
{
vis[vx[now][j].idx] = ; break;
}
}
} else {
// y
now -= ;
int cnt = ;
for(int j=;j<vy[now].size();j++) if(vis[vy[now][j].idx]<) cnt++;
if( cnt== ) {
for(int j=;j<vy[now].size();j++) if(vis[vy[now][j].idx]<){
vis[vy[now][j].idx] = ;
break;
}
}
}
}
} bool res = true;
for(int i=;i<tot;i++){
// printf("vis[%d]=%d\n",i,vis[i]);
if(vis[i]<&&i!=out) {
res = false;
break;
}
} return res;
} int main() {
tot = ;
scanf("%d",&n);
for(int i=;i<n;i++){
char buf[];
scanf("%s",buf);
POINT pt = GetPoint(buf);
if( se.find(pt.hash) == se.end() ){
se.insert(pt.hash);
pt.idx = tot++;
pts.PB(pt);
}
} // for(int i=0;i<pts.size();i++){
// printf("%d,%d\n",pts[i].x,pts[i].y);
// }
// printf("size = %d\n",pts.size()); SplitPoints();
int ans = *tot;
for(int i=;i<(<<);i++) {
for(int j=;j<tot;j++){
if( check(i,j) ) {
//if(__builtin_popcount(i)==10&&fff==-1) printf("i=%d , ans = %d\n",i,__builtin_popcount(i));
ans = min( ans,__builtin_popcount(i) );
}
}
}
// printf("tot = %d\n", tot);
printf("%d\n",ans);
return ;
}