浙江省赛 C What Kind of Friends Are You?

来源:互联网 发布:淘宝宝贝导出excel 编辑:程序博客网 时间:2024/05/17 07:01

            思路:一开始考虑n个朋友可以有c种可能,根据回答的问题,如果是yes那么可以确定一些朋友的范围,将原本不在这个范围内的删除即可;如果是“no”,说明这些朋友都应该被删除,那么最后看第i个人候选的情况是不是只有一种,如果是直接输出名字,否则就是不确定或者不存在。下面介绍利用贡献优化,并且非常好写的方法。

AC代码

#include <cstdio>#include <cmath>#include <cctype>#include <algorithm>#include <cstring>#include <utility>#include <string>#include <iostream>#include <map>#include <set>#include <vector>#include <queue>#include <stack>using namespace std;#pragma comment(linker, "/STACK:1024000000,1024000000") #define eps 1e-10#define inf 0x3f3f3f3f#define PI pair<int, int> typedef long long LL;const int maxn = 200 + 5;string name[maxn];int vis[maxn][maxn];int a[maxn][maxn];map<string, int>ha;int getId(string p) {return ha[p];}int main() {int T, n, q, c;scanf("%d", &T);while(T--) {ha.clear();scanf("%d%d", &n, &q);scanf("%d", &c);for(int i = 0; i < c; ++i) {cin >> name[i];ha[name[i]] = i;}vector<int>que[maxn];memset(vis, 0, sizeof(vis));for(int i = 0; i < q; ++i) {int m;scanf("%d", &m);string s;for(int j = 0; j < m; ++j) {cin >> s;que[i].push_back(getId(s));}}for(int i = 0; i < n; ++i) {for(int j = 0; j < c; ++j) vis[i][j] = 1;for(int j = 0; j < q; ++j) {scanf("%d", &a[i][j]);if(a[i][j]) {for(int k = 0; k < c; ++k) if(vis[i][k]) {int f = 0;for(int h = 0; h < que[j].size(); ++h) {if(que[j][h] == k) {f = 1;break;}}if(!f) vis[i][k] = 0;}}else {for(int k = 0; k < que[j].size(); ++k) {vis[i][que[j][k]] = 0;}}}}for(int i = 0; i < n; ++i) {int cnt = 0;int ind;for(int j = 0; j < c; ++j) {if(vis[i][j]) {++cnt;ind = j;}}if(cnt == 1) {cout << name[ind] << endl;}else printf("Let's go to the library!!\n");}}return 0;}


    更好的思路:每一个人被每一个问题赋予了一定的贡献,第i个问题的贡献是2^i(二进制)。

  例如:

4 Serval Raccoon Alpaca Moose
1 Serval
1 Fennec
1 Serval

第一个问题对Serval Raccoon Alpaca Moose四人的贡献为2^0,

第二个问题对Serval贡献为2^1,下面的问题同理;“”

最后根据对问题的回答情况,确定第i(0 < i < n)人的贡献,查找人名中是否有唯一与之对应的,如果有输出人名,否则输出“Let's go to the library!!”,时间复杂度为O(n*c)。这种方法非常巧妙,降低了复杂度。

AC代码

#include <cstdio>#include <cmath>#include <cctype>#include <algorithm>#include <cstring>#include <utility>#include <string>#include <iostream>#include <map>#include <set>#include <vector>#include <queue>#include <stack>using namespace std;#pragma comment(linker, "/STACK:1024000000,1024000000") #define eps 1e-10#define inf 0x3f3f3f3f#define PI pair<int, int> typedef long long LL;const int maxn = 200 + 5;string name[maxn];map<string, int>ha;int w[30], g[maxn];void init() {w[0] = 1;for(int i = 1; i <= 25; ++i) w[i] = w[i-1] * 2;}int main() {init();int T, n, q, c;scanf("%d", &T);while(T--) {ha.clear();scanf("%d%d", &n, &q);scanf("%d", &c);for(int i = 0; i < c; ++i) {cin >> name[i];ha[name[i]] = i;g[i] = 0;}for(int i = 0; i < q; ++i) {string s;int m;scanf("%d", &m);while(m--) {cin >> s;g[ha[s]] += w[i];}}for(int i = 0; i < n; ++i) {int sum = 0;for(int j = 0; j < q; ++j) {int f;scanf("%d", &f);if(f) sum += w[j];}int cnt = 0, peo;for(int j = 0; j < c; ++j) {if(g[j] == sum) {++cnt;peo = j;}}if(cnt == 1) cout << name[peo] << endl;else printf("Let's go to the library!!\n");}}return 0;}

由于测试数据不够强,导致二种方法时间相差不大:强烈建议掌握第二种的思路。


如有不当之处欢迎指出!

1 0
原创粉丝点击