2010TianjinRegional 部分题解
比赛链接:http://acm.hust.edu.cn/vjudge/contest/129879#overview
A.Arranging Your Team
题意:给你23个人的姓名,分数,位置。让你从这23个人里挑选出一个4-4-2-1的阵容,每两个人之间会相互影响,取决于一个值。求一种挑选方法,使得整个分数最大。
4-4-2-1,每个人的职责不一样,这个复杂度分析起来挺玄学的。暴力搜索,分职责去挑选,最终挑选完毕统计结果即可。也可以用状压直接枚举,复杂度应该是一样的。注意这里应当把姓名离散化,否则会TLE(不离散化大概一个样例要跑5s,不要问我怎么知道的…)
1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <algorithm> 18 #include <iostream> 19 #include <iomanip> 20 #include <cstring> 21 #include <climits> 22 #include <complex> 23 #include <fstream> 24 #include <cassert> 25 #include <cstdio> 26 #include <bitset> 27 #include <vector> 28 #include <deque> 29 #include <queue> 30 #include <stack> 31 #include <ctime> 32 #include <set> 33 #include <map> 34 #include <cmath> 35 using namespace std; 36 #define fr first 37 #define sc second 38 #define cl clear 39 #define BUG puts("here!!!") 40 #define W(a) while(a--) 41 #define pb(a) push_back(a) 42 #define Rint(a) scanf("%d", &a) 43 #define Rll(a) scanf("%I64d", &a) 44 #define Rs(a) scanf("%s", a) 45 #define Cin(a) cin >> a 46 #define FRead() freopen("in", "r", stdin) 47 #define FWrite() freopen("out", "w", stdout) 48 #define Rep(i, len) for(int i = 0; i < (len); i++) 49 #define For(i, a, len) for(int i = (a); i < (len); i++) 50 #define Cls(a) memset((a), 0, sizeof(a)) 51 #define Clr(a, x) memset((a), (x), sizeof(a)) 52 #define Full(a) memset((a), 0x7f7f7f, sizeof(a)) 53 #define lrt rt << 1 54 #define rrt rt << 1 | 1 55 #define pi 3.14159265359 56 #define RT return 57 #define lowbit(x) x & (-x) 58 #define onecnt(x) __builtin_popcount(x) 59 typedef long long LL; 60 typedef long double LD; 61 typedef unsigned long long ULL; 62 typedef pair<int, int> pii; 63 typedef pair<string, int> psi; 64 typedef pair<LL, LL> pll; 65 typedef map<string, int> msi; 66 typedef vector<int> vi; 67 typedef vector<LL> vl; 68 typedef vector<vl> vvl; 69 typedef vector<bool> vb; 70 71 const int maxn = 33; 72 typedef struct Node { 73 int id; 74 string name; 75 int s; 76 int t; 77 }Node; 78 Node fuck; 79 int n, m; 80 string tmp; 81 int ret; 82 vector<Node> peo[6]; 83 int G[maxn][maxn]; 84 vector<int> ans; 85 int score[maxn]; 86 map<string, int> ns; 87 88 int get() { 89 if(tmp[0] == 'g') return 1; 90 else if(tmp[0] == 'd') return 2; 91 else if(tmp[0] == 'm') return 3; 92 else if(tmp[0] == 's') return 4; 93 } 94 95 void dfs1(int cur, int cnt); 96 void dfs2(int cur, int cnt); 97 void dfs3(int cur, int cnt); 98 void dfs4(int cur, int cnt); 99 100 void dfs1(int cur, int cnt) { 101 if(cnt == 1) { 102 dfs2(-1, 0); 103 return; 104 } 105 For(i, cur+1, peo[1].size()) { 106 ans.push_back(peo[1][i].id); 107 dfs1(i, cnt+1); 108 ans.pop_back(); 109 } 110 } 111 112 void dfs2(int cur, int cnt) { 113 if(cnt == 4) { 114 dfs3(-1, 0); 115 return; 116 } 117 For(i, cur+1, peo[2].size()) { 118 ans.push_back(peo[2][i].id); 119 dfs2(i, cnt+1); 120 ans.pop_back(); 121 } 122 } 123 124 void dfs3(int cur, int cnt) { 125 if(cnt == 4) { 126 dfs4(-1, 0); 127 return; 128 } 129 For(i, cur+1, peo[3].size()) { 130 ans.push_back(peo[3][i].id); 131 dfs3(i, cnt+1); 132 ans.pop_back(); 133 } 134 } 135 136 void dfs4(int cur, int cnt) { 137 if(cnt == 2) { 138 int sum = 0; 139 Rep(i, ans.size()) { 140 For(j, i+1, ans.size()) { 141 sum += G[ans[i]][ans[j]]; 142 } 143 sum += score[ans[i]]; 144 } 145 ret = max(ret, sum); 146 return; 147 } 148 For(i, cur+1, peo[4].size()) { 149 ans.push_back(peo[4][i].id); 150 dfs4(i, cnt+1); 151 ans.pop_back(); 152 } 153 } 154 155 int main() { 156 // FRead(); 157 int id = 1; 158 while(cin >> fuck.name >> fuck.s >> tmp) { 159 ret = -0x7f7f7f; Cls(score); Cls(G); 160 For(i, 1, 5) peo[i].clear(); id = 1; ns.clear(); ans.clear(); 161 162 fuck.t = get(); ns[fuck.name] = id++; 163 score[id-1] = fuck.s; 164 fuck.id = id - 1; 165 peo[fuck.t].pb(fuck); 166 For(i, 2, 24) { 167 cin >> fuck.name >> fuck.s >> tmp; 168 fuck.t = get(); ns[fuck.name] = id++; 169 score[id-1] = fuck.s; 170 fuck.id = id - 1; 171 peo[fuck.t].pb(fuck); 172 } 173 Rint(m); 174 string a, b; 175 int sc; 176 Rep(i, m) { 177 cin >> a >> b >> sc; 178 G[ns[a]][ns[b]] = G[ns[b]][ns[a]] = sc; 179 } 180 if(peo[1].size()<1||peo[2].size()<4||peo[3].size()<4||peo[4].size()<2) { 181 printf("impossible\n"); 182 continue; 183 } 184 dfs1(-1, 0); 185 printf("%d\n", ret); 186 } 187 RT 0; 188 }
C.Card Game
题意:给n个字符串,让它们两两配对,比如字符串i和j,让i和j的翻转重叠的最多。
根据i,j的重叠字符数量建图G(i,j),跑KM。模版题,注意别忘了初始化nx, ny…
1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <algorithm> 18 #include <iostream> 19 #include <iomanip> 20 #include <cstring> 21 #include <climits> 22 #include <complex> 23 #include <fstream> 24 #include <cassert> 25 #include <cstdio> 26 #include <bitset> 27 #include <vector> 28 #include <deque> 29 #include <queue> 30 #include <stack> 31 #include <ctime> 32 #include <set> 33 #include <map> 34 #include <cmath> 35 using namespace std; 36 #define fr first 37 #define sc second 38 #define cl clear 39 #define BUG puts("here!!!") 40 #define W(a) while(a--) 41 #define pb(a) push_back(a) 42 #define Rint(a) scanf("%d", &a) 43 #define Rll(a) scanf("%I64d", &a) 44 #define Rs(a) scanf("%s", a) 45 #define Cin(a) cin >> a 46 #define FRead() freopen("in", "r", stdin) 47 #define FWrite() freopen("out", "w", stdout) 48 #define Rep(i, len) for(int i = 0; i < (len); i++) 49 #define For(i, a, len) for(int i = (a); i < (len); i++) 50 #define Cls(a) memset((a), 0, sizeof(a)) 51 #define Clr(a, x) memset((a), (x), sizeof(a)) 52 #define Full(a) memset((a), 0x7f7f7f, sizeof(a)) 53 #define lrt rt << 1 54 #define rrt rt << 1 | 1 55 #define pi 3.14159265359 56 #define RT return 57 #define lowbit(x) x & (-x) 58 #define onecnt(x) __builtin_popcount(x) 59 typedef long long LL; 60 typedef long double LD; 61 typedef unsigned long long ULL; 62 typedef pair<int, int> pii; 63 typedef pair<string, int> psi; 64 typedef pair<LL, LL> pll; 65 typedef map<string, int> msi; 66 typedef vector<int> vi; 67 typedef vector<LL> vl; 68 typedef vector<vl> vvl; 69 typedef vector<bool> vb; 70 71 /* KM算法 72 * 复杂度O(nx*nx*ny) 73 * 求最大权匹配 74 * 若求最小权匹配,可将权值取相反数,结果取相反数 75 * 点的编号从0开始 76 */ 77 const int maxn = 310; 78 const int inf = 0x3f3f3f3f; 79 int nx,ny;//两边的点数,注意修改 80 int G[maxn][maxn];//二分图描述 81 int linker[maxn],lx[maxn],ly[maxn];//y中各点匹配状态,x,y中的点标号 82 int slack[maxn]; 83 bool visx[maxn],visy[maxn]; 84 85 bool dfs(int x) { 86 visx[x] = true; 87 for(int y = 0; y < ny; y++) { 88 if(visy[y])continue; 89 int tmp = lx[x] + ly[y] - G[x][y]; 90 if(tmp == 0) { 91 visy[y] = true; 92 if(linker[y] == -1 || dfs(linker[y])) { 93 linker[y] = x; 94 return true; 95 } 96 } 97 else if(slack[y] > tmp) 98 slack[y] = tmp; 99 } 100 return false; 101 } 102 int km() { 103 memset(linker,-1,sizeof(linker)); 104 memset(ly,0,sizeof(ly)); 105 for(int i = 0;i < nx;i++) { 106 lx[i] = -inf; 107 for(int j = 0;j < ny;j++) 108 if(G[i][j] > lx[i]) 109 lx[i] = G[i][j]; 110 } 111 for(int x = 0;x < nx;x++) { 112 for(int i = 0;i < ny;i++) 113 slack[i] = inf; 114 while(true) { 115 memset(visx,false,sizeof(visx)); 116 memset(visy,false,sizeof(visy)); 117 if(dfs(x))break; 118 int d = inf; 119 for(int i = 0;i < ny;i++) 120 if(!visy[i] && d > slack[i]) 121 d = slack[i]; 122 for(int i = 0;i < nx;i++) 123 if(visx[i]) 124 lx[i] -= d; 125 for(int i = 0;i < ny;i++) { 126 if(visy[i])ly[i] += d; 127 else slack[i] -= d; 128 } 129 } 130 } 131 int res = 0; 132 for(int i = 0;i < ny;i++) 133 if(linker[i] != -1) 134 res += G[linker[i]][i]; 135 return res; 136 } 137 138 int n; 139 string s[maxn]; 140 141 int get(string a, string b) { 142 int ret = 0; 143 int i, j; 144 for(i = a.length() - 1, j = 0; a[i] && b[j]; i--, j++) { 145 if(a[i] != b[j]) return ret; 146 else ret++; 147 } 148 return ret; 149 } 150 151 int main() { 152 // FRead(); 153 while(~Rint(n)) { 154 Cls(G); 155 nx = ny = n; 156 Rep(i, n) cin >> s[i]; 157 Rep(i, n) { 158 Rep(j, n) { 159 if(i == j) continue; 160 G[i][j] = get(s[i], s[j]); 161 } 162 } 163 printf("%d\n", km()); 164 } 165 RT 0; 166 }
D.Delta Wave
题意:在一个网格上,若限定每步只能向右移动一格,可以右上,右下,横向,向右,并禁止移动到以下的地方,则以这种走法移动步从到的可能形成的路径的总数为的默慈金数。
大数+默慈金数,直接搬了http://blog.csdn.net/acdreamers/article/details/41213667
1 //默慈金数 2 // Mn = ∑C(n, 2*i) Catalan(i) 3 import java.math.*; 4 import java.util.*; 5 6 public class Main { 7 8 public static final int N = 10005; 9 public static final BigInteger MOD = BigInteger.valueOf(10).pow(100); 10 public static BigInteger ans[] = new BigInteger[N]; 11 public static void Init(){ 12 ans[1] = BigInteger.valueOf(1); 13 ans[2] = BigInteger.valueOf(2); 14 for(int i = 3; i < N; i++){ 15 BigInteger a = ans[i - 1].multiply((BigInteger.valueOf(2).multiply(BigInteger.valueOf(i)).add(BigInteger.valueOf(1)))); 16 BigInteger b = ans[i - 2].multiply((BigInteger.valueOf(3).multiply(BigInteger.valueOf(i)).subtract(BigInteger.valueOf(3)))); 17 ans[i] = (a.add(b)).divide(BigInteger.valueOf(i).add((BigInteger.valueOf(2)))); 18 } 19 } 20 21 public static void main(String[] args){ 22 Init(); 23 Scanner cin = new Scanner(System.in); 24 while(cin.hasNext()){ 25 int n = cin.nextInt(); 26 System.out.println(ans[n].mod(MOD)); 27 } 28 } 29 }
E.Encoded Barcodes
题意:给一个字典和m个条形码,条形码的条形有粗有细,在一个阈值外是粗,阈值内是细。把条形码转换成字符串后是字典中的多少个字符串的前缀,统计m个条形码的总和。
字典树,条形码区分01的时候是和平均数做的比较,比平均数大是1,小是0。不能用cin,会TLE。
1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <algorithm> 18 #include <iostream> 19 #include <iomanip> 20 #include <cstring> 21 #include <climits> 22 #include <complex> 23 #include <fstream> 24 #include <cassert> 25 #include <cstdio> 26 #include <bitset> 27 #include <vector> 28 #include <deque> 29 #include <queue> 30 #include <stack> 31 #include <ctime> 32 #include <set> 33 #include <map> 34 #include <cmath> 35 using namespace std; 36 #define fr first 37 #define sc second 38 #define cl clear 39 #define BUG puts("here!!!") 40 #define W(a) while(a--) 41 #define pb(a) push_back(a) 42 #define Rint(a) scanf("%d", &a) 43 #define Rll(a) scanf("%I64d", &a) 44 #define Rs(a) scanf("%s", a) 45 #define Cin(a) cin >> a 46 #define FRead() freopen("in", "r", stdin) 47 #define FWrite() freopen("out", "w", stdout) 48 #define Rep(i, len) for(int i = 0; i < (len); i++) 49 #define For(i, a, len) for(int i = (a); i < (len); i++) 50 #define Cls(a) memset((a), 0, sizeof(a)) 51 #define Clr(a, x) memset((a), (x), sizeof(a)) 52 #define Full(a) memset((a), 0x7f7f7f, sizeof(a)) 53 #define lrt rt << 1 54 #define rrt rt << 1 | 1 55 #define pi 3.14159265359 56 #define RT return 57 #define lowbit(x) x & (-x) 58 #define onecnt(x) __builtin_popcount(x) 59 typedef long long LL; 60 typedef long double LD; 61 typedef unsigned long long ULL; 62 typedef pair<int, int> pii; 63 typedef pair<string, int> psi; 64 typedef pair<LL, LL> pll; 65 typedef map<string, int> msi; 66 typedef vector<int> vi; 67 typedef vector<LL> vl; 68 typedef vector<vl> vvl; 69 typedef vector<bool> vb; 70 71 typedef struct Node { 72 int cnt; 73 Node* next[26]; 74 Node() { 75 cnt = 0; 76 Rep(i, 26) next[i] = NULL; 77 } 78 }Node; 79 80 Node* rt; 81 Node memory[110000]; 82 int mcnt; 83 84 void insert(Node* p, string str) { 85 for(int i = 0; str[i]; i++) { 86 if(p->next[str[i]-'a'] == NULL) { 87 p->next[str[i]-'a'] = &memory[mcnt++]; 88 } 89 p = p->next[str[i]-'a']; 90 p->cnt++; 91 } 92 } 93 94 int find(Node* p, string str) { 95 for(int i = 0; str[i]; i++) { 96 int t = str[i] - 'a'; 97 if(p->next[t] == NULL) return 0; 98 p = p->next[t]; 99 } 100 return p->cnt; 101 } 102 103 int n, m, k; 104 105 inline bool scan_lf(double &num) { 106 char in;double Dec=0.1; 107 bool IsN=false,IsD=false; 108 in=getchar(); 109 if(in==EOF) return false; 110 while(in!='-'&&in!='.'&&(in<'0'||in>'9')) 111 in=getchar(); 112 if(in=='-'){IsN=true;num=0;} 113 else if(in=='.'){IsD=true;num=0;} 114 else num=in-'0'; 115 if(!IsD){ 116 while(in=getchar(),in>='0'&&in<='9'){ 117 num*=10;num+=in-'0';} 118 } 119 if(in!='.'){ 120 if(IsN) num=-num; 121 return true; 122 }else{ 123 while(in=getchar(),in>='0'&&in<='9'){ 124 num+=Dec*(in-'0');Dec*=0.1; 125 } 126 } 127 if(IsN) num=-num; 128 return true; 129 } 130 131 string get(int k) { 132 string ret; 133 Rep(i, k) { 134 double a[10]; 135 double sum = 0.0; 136 Rep(j, 8) { 137 scan_lf(a[j]); 138 sum += a[j]; 139 } 140 sum /= 8; 141 int ch = 0; 142 Rep(j, 8) { 143 ch <<= 1; 144 ch |= (a[j] > sum); 145 } 146 ret.push_back(ch); 147 } 148 return ret; 149 } 150 151 int main() { 152 // FRead(); 153 string tmp; 154 while(cin >> n >> m) { 155 mcnt = 0; Cls(memory); 156 rt = &memory[mcnt++]; 157 // rt = new Node(); 158 Rep(i, n) { 159 cin >> tmp; 160 insert(rt, tmp); 161 } 162 int ret = 0; 163 W(m) { 164 Rint(k); 165 tmp = get(k); 166 ret += find(rt, tmp); 167 } 168 printf("%d\n", ret); 169 } 170 RT 0; 171 }
I.I'm Telling the Truth
题意:n个人说自己的名次区间,其中有人是说谎的。求说谎人最少的情况,输出说真话的人数,要反字典序(最大的几个)。
贪心无法得到规定的序列,应该按区间的左右端点建二分图,跑匈牙利算法。
1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <algorithm> 18 #include <iostream> 19 #include <iomanip> 20 #include <cstring> 21 #include <climits> 22 #include <complex> 23 #include <cassert> 24 #include <cstdio> 25 #include <bitset> 26 #include <vector> 27 #include <deque> 28 #include <queue> 29 #include <stack> 30 #include <ctime> 31 #include <set> 32 #include <map> 33 #include <cmath> 34 using namespace std; 35 #define fr first 36 #define sc second 37 #define cl clear 38 #define BUG puts("here!!!") 39 #define W(a) while(a--) 40 #define pb(a) push_back(a) 41 #define Rint(a) scanf("%d", &a) 42 #define Rs(a) scanf("%s", a) 43 #define Cin(a) cin >> a 44 #define FRead() freopen("in", "r", stdin) 45 #define FWrite() freopen("out", "w", stdout) 46 #define Rep(i, len) for(int i = 0; i < (len); i++) 47 #define For(i, a, len) for(int i = (a); i < (len); i++) 48 #define Cls(a) memset((a), 0, sizeof(a)) 49 #define Clr(a, x) memset((a), (x), sizeof(a)) 50 #define Full(a) memset((a), 0x7f7f7f, sizeof(a)) 51 #define lrt rt << 1 52 #define rrt rt << 1 | 1 53 #define pi 3.14159265359 54 #define RT return 55 #define lowbit(x) x & (-x) 56 #define onenum(x) __builtin_popcount(x) 57 typedef long long LL; 58 typedef long double LD; 59 typedef unsigned long long ULL; 60 typedef pair<int, int> pii; 61 typedef pair<string, int> psi; 62 typedef pair<LL, LL> pll; 63 typedef map<string, int> msi; 64 typedef vector<int> vi; 65 typedef vector<LL> vl; 66 typedef vector<vl> vvl; 67 typedef vector<bool> vb; 68 69 const int maxn = 110; 70 const int maxm = 200100; 71 int x[maxn], y[maxn], linker[maxm]; 72 int n, ret; 73 int ok[maxn]; 74 bool vis[maxm]; 75 76 bool dfs(int u) { 77 For(i, x[u], y[u]+1) { 78 if(!vis[i]) { 79 vis[i] = 1; 80 if(linker[i] == -1 || dfs(linker[i])) { 81 linker[i] = u; 82 ok[u] = i; 83 return 1; 84 } 85 } 86 } 87 return 0; 88 } 89 90 int main() { 91 // FRead(); 92 int T; 93 Rint(T); 94 W(T) { 95 Rint(n); 96 Cls(ok); Clr(linker, -1); Cls(vis); ret = 0; 97 For(i, 1, n+1) { 98 Rint(x[i]); Rint(y[i]); 99 } 100 for(int i = n; i >= 1; i--) { 101 Cls(vis); 102 if(dfs(i)) ret++; 103 } 104 printf("%d\n", ret); 105 vi fuck; 106 For(i, 1, n+1) { 107 if(ok[i]) fuck.pb(i); 108 } 109 printf("%d", fuck[0]); 110 For(i, 1, fuck.size()) printf(" %d", fuck[i]); 111 printf("\n"); 112 } 113 RT 0; 114 }