[CF442A] Borya and Hanabi (暴力bitmask)

题目链接:http://codeforces.com/problemset/problem/442/A

题目大意:给你n张卡片,你知道这n张卡片都是什么,但是不知道他们的位置。你每次可以请求朋友指出一种颜色的卡片,或者一种数字的卡片。问你最少需要多少次能够知道每个卡片的位置。

首先,如果其他所有卡片都知道了,最后一张卡片不需要指示就知道了。

然后我们枚举哪张是最后一张卡片。

将五种颜色放在x轴,5个数字放在y轴。

一次询问就是画一条线,先去掉交叉点,再看剩下的点是不是唯一在一条直线里。

bitmask,一共最多25条线。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <map>
  6 #include <set>
  7 #include <bitset>
  8 #include <cmath>
  9 #include <numeric>
 10 #include <iterator>
 11 #include <iostream>
 12 #include <cstdlib>
 13 #include <functional>
 14 #include <queue>
 15 #include <stack>
 16 #include <string>
 17 #include <cctype>
 18 using namespace std;
 19 #define PB push_back
 20 #define MP make_pair
 21 #define SZ size()
 22 #define ST begin()
 23 #define ED end()
 24 #define CLR clear()
 25 #define ZERO(x) memset((x),0,sizeof(x))
 26 typedef long long LL;
 27 typedef unsigned long long ULL;
 28 typedef pair<int,int> PII;
 29 const double EPS = 1e-8;
 30
 31 struct POINT{
 32     int x,y;
 33     int hash,idx;
 34 };
 35
 36 int n,tot;
 37 vector<POINT> pts;
 38 set<int> se;
 39 vector<POINT> vx[10],vy[10];
 40
 41 POINT GetPoint(const char* buf){
 42     POINT res;
 43     if( buf[0] == ‘R‘ ) res.x = 1;
 44     else if( buf[0] ==‘G‘ ) res.x = 2;
 45     else if( buf[0] == ‘B‘ ) res.x = 3;
 46     else if( buf[0] == ‘Y‘ ) res.x = 4;
 47     else if( buf[0] == ‘W‘ ) res.x = 5;
 48     res.y = buf[1] -‘0‘;
 49     res.hash = res.x*10+res.y;
 50     return res;
 51 }
 52
 53 void SplitPoints() {
 54     for(int i=0;i<pts.size();i++){
 55         POINT &pt = pts[i];
 56         vx[pt.x].PB(pt);
 57         vy[pt.y].PB(pt);
 58
 59 //        printf("vx[%d].PB(%d)\n",pt.x,pt.idx);
 60 //        printf("vy[%d].PB(%d)\n",pt.y,pt.idx);
 61     }
 62 }
 63
 64 bool check(int mask,int out) {
 65
 66     int vis[33];
 67     for(int i=0;i<33;i++) vis[i] = 0;
 68
 69     for( int i=0;i<10;i++ ){
 70         if( (mask>>i)&1 ) {
 71             int now = i+1;
 72             if(now<=5) {
 73                 if( vx[now].size()==0 ) return false;
 74             } else {
 75                 now -= 5;
 76                 if( vy[now].size()==0 ) return false;
 77             }
 78         }
 79     }
 80
 81 //    if(mask==261) puts("****");
 82
 83     for( int i=0;i<10;i++ ) {
 84         if( (mask>>i)&1 ) {
 85             int now = i+1;
 86 //            if(mask==261) printf("now i=%d\n",now);
 87             if( now<=5 ) {
 88                 for(int j=0;j<vx[now].size();j++){
 89                     if( vis[vx[now][j].idx] == 2 ) continue;
 90                     vis[vx[now][j].idx]++;
 91                 }
 92             } else {
 93                 now -= 5;
 94                 for(int j=0;j<vy[now].size();j++){
 95                     if( vis[vy[now][j].idx]==2 ) continue;
 96                     vis[vy[now][j].idx]++;
 97                 }
 98             }
 99         }
100     }
101
102     for(int i=0;i<10;i++){
103         if( (mask>>i)&1 ) {
104             int now = i+1;
105             if( now<=5 ) {
106                 // x
107                 int cnt = 0;
108                 for(int j=0;j<vx[now].size();j++) if(vis[vx[now][j].idx]<2) cnt++;
109                 if( cnt==1 ) {
110                     for(int j=0;j<vx[now].size();j++) if( vis[vx[now][j].idx] < 2)
111                     {
112                         vis[vx[now][j].idx] = 2; break;
113                     }
114                 }
115             } else {
116                 // y
117                 now -= 5;
118                 int cnt = 0;
119                 for(int j=0;j<vy[now].size();j++) if(vis[vy[now][j].idx]<2) cnt++;
120                 if( cnt==1 ) {
121                     for(int j=0;j<vy[now].size();j++) if(vis[vy[now][j].idx]<2){
122                         vis[vy[now][j].idx] = 2;
123                         break;
124                     }
125                 }
126             }
127         }
128     }
129
130     bool res = true;
131     for(int i=0;i<tot;i++){
132 //        printf("vis[%d]=%d\n",i,vis[i]);
133         if(vis[i]<2&&i!=out) {
134             res = false;
135             break;
136         }
137     }
138
139     return res;
140 }
141
142
143
144 int main() {
145     tot = 0;
146     scanf("%d",&n);
147     for(int i=0;i<n;i++){
148         char buf[11];
149         scanf("%s",buf);
150         POINT pt = GetPoint(buf);
151         if( se.find(pt.hash) == se.end() ){
152             se.insert(pt.hash);
153             pt.idx = tot++;
154             pts.PB(pt);
155         }
156     }
157
158 //    for(int i=0;i<pts.size();i++){
159 //        printf("%d,%d\n",pts[i].x,pts[i].y);
160 //    }
161 //    printf("size = %d\n",pts.size());
162
163     SplitPoints();
164     int ans = 2*tot;
165     for(int i=0;i<(1<<10);i++) {
166         for(int j=0;j<tot;j++){
167             if( check(i,j) ) {
168                 //if(__builtin_popcount(i)==10&&fff==-1) printf("i=%d , ans = %d\n",i,__builtin_popcount(i));
169                 ans = min( ans,__builtin_popcount(i) );
170             }
171         }
172     }
173 //    printf("tot = %d\n", tot);
174     printf("%d\n",ans);
175     return 0;
176 }
时间: 2024-08-04 22:18:08

[CF442A] Borya and Hanabi (暴力bitmask)的相关文章

Codeforces 443A Borya and Hanabi(暴力)

题目链接:Codeforces 443A Borya and Hanabi 题目大意:有若干个牌,每张牌有花色和数字两个值,现在问说至少询问多少次才能区分出所有的牌,每次询问可以确定一种花色牌的位置,或者是一种数字牌的位置. 解题思路:暴力枚举需要问的花色和数字,210,然后枚举两两判断是否可以被区分. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const

Codeforces Round #253 (Div. 2)——Borya and Hanabi

题目连接 题意: n表示有n个卡片,每个卡片有一种颜色和一个数字(共五种不同的颜色和五个不同的数字).事先知道每种卡片有几张,但是不知道具体的位置.问需要几次提示就可以知道所有卡片的位置都在哪里:每次提示可以选择一个颜色或者一个数字,就可以知道含有所选属性的牌有哪些. 分析: 首先明白总情况数不多,只有2^10,所以枚举. 能确定某张牌位置的情况:1)提示了一个属性,而这个属性只有一张牌 2)某个属性有n张牌,知道了n-1张牌的位置 两个提示确定一张牌:必然的,只要存在这张牌,那么两个提示必然可

Codeforces 442A Borya and Hanabi

有五种花色 外加 五种点数 共25张牌,每次有n张牌,主人知道这n张牌中有哪些牌,并且哪种牌有几张,但是不知道具体是哪张牌,他可以问某种花色,然后知道了哪几张是该花色,也可以问点数,然后就知道了哪几张是这个点数.最终可以把所有牌都确定下来,问最少要询问几次. 这个题目一开始想到枚举(事实证明最后就是枚举),然后又想到二分图去了,..主要是这个花色对应点数,连成边之后太像二分图了,而且感觉为了得到所有的牌,隐隐约约有点像 DAG上的最小点覆盖...而且看了下样例,有点像,所以就去敲二分图去了,结果

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734

Codeforces Round 253 (Div. 2)

layout: post title: Codeforces Round 253 (Div. 2) author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces - 模拟栈 - 贪心 传送门 A.Anton and Letters (签到) 题意 判断字符串里面有多少个不同字符 思路 直接set一下 #include<bits/stdc++.h> using namespace std; typed

暑假集训-个人赛第三场

ID Origin Title 10 / 29 Problem A CodeForces 443B Kolya and Tandem Repeat   1 / 1 Problem B CodeForces 442A Borya and Hanabi 9 / 29 Problem C CodeForces 442B Andrey and Problem 3 / 17 Problem D CodeForces 442C Artem and Array 14 / 18 Problem E CodeFo

二叉树的后序遍历(暴力版) 小白菜oj 1034

给出二叉树的前序遍历和中序遍历,求二叉树的后序遍历-- 作为一个搜索蒟蒻,我真的没有办法很和谐的A掉,但估计过几天就会写有关这个题的和谐的解法--但只是估计-- 下面讲述我的超暴力解法-- 首先,先由前序遍历得到一个父亲节点,然后再由中序遍历得到这个父亲节点的左子树和右子树中的元素(中序遍历中,该点的左边的所有点,都在它的左子树,右边的都在它的右子树,子树中的根节点是在这些节点的前序遍历中排名最靠前的),然后递归建树,之后在递归求后序遍历即可. 但这个方法有两个比较--&¥--&的问题:1

玲珑杯 round18 A 计算几何瞎暴力

题目链接 : http://www.ifrog.cc/acm/problem/1143 当时没看到坐标的数据范围= =看到讨论才意识到,不同的坐标最多只有1k多个,完全可以暴力做法,不过也要一些技巧. 首先注意数很大可能爆int,用LL得话注意强制转换或者全设为LL,假如  int a=50000,b=a;  LL sum=a*b; 则会爆出,除非ab都是LL 或者 sum=(LL)a*(LL)b; 还有就是R最大就是30,我们不妨设ans[i]表示R<=i的组合个数,做一个前缀和方便快速询问.

Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】

弱弱的战壕 描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒[email protected][email protected]). 但是,战壕有一个弱点,就是只能攻击它的左下方,说白了就是横纵坐标都不大于它的点(mx:“我的战壕为什么这么菜”ToT).这样,永恒就可以从别的地方进攻摧毁战壕,从而消灭mx的部队. 战壕都有一个保护范围,同它的攻击