zoukankan      html  css  js  c++  java
  • [洛谷P1278]单词游戏

    题目大意:给一个有$n(nleqslant16)$个单词的字典,求单词接龙的最大长度

    题解:发现$n$很小,可以状压,令$f_{i,j}$表示选的数的状态为$i$,最后一个字母是$j$的最大长度。

    卡点:

    C++ Code:

    #include <cstdio>
    #include <cstring>
    #define maxn 16
    #define N (1 << maxn | 3)
    char s[105];
    int n, len[maxn], l[maxn], r[maxn];
    int f[N][6];
    inline int get(char x) {
    	switch (x) {
    		case 'A': return 1;
    		case 'E': return 2;
    		case 'I': return 3;
    		case 'O': return 4;
    		case 'U': return 5;
    		default: return 20040826;
    	}
    }
    int q[N], h, t = -1, ans;
    bool inq[N];
    inline int max(int a, int b) {return a < b ? a : b;}
    inline void getmax(int &a, int b) {if (a < b) a = b;}
    int main() {
    	scanf("%d", &n);
    	for (int i = 0; i < n; i++) {
    		scanf("%s", s);
    		len[i] = strlen(s);
    		l[i] = get(s[0]); r[i] = get(s[len[i] - 1]);
    		f[1 << i][r[i]] = len[i];
    		getmax(ans, f[1 << i][r[i]]);
    		inq[q[++t] = 1 << i] = true;
    	}
    	while (h <= t) {
    		int u = q[h++];
    		for (int i = 1; i <= 5; i++) if (f[u][i]) {
    			for (int j = 0; j < n; j++) if (!(u & 1 << j)) {
    				int v = u | 1 << j;
    				if (l[j] == i) {
    					getmax(f[v][r[j]], f[u][i] + len[j]);
    					getmax(ans, f[v][r[j]]);
    					if (!inq[v]) inq[q[++t] = v] = true;
    				}
    			}
    		}
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

  • 相关阅读:
    折半枚举(双向搜索)
    弹性碰撞
    集合的整数表示
    反转(开关问题)
    尺取法
    floor函数用法
    二分搜索
    4. 差分约束系统
    二叉树的表达式求值
    关于移动app开发的一些不错的站点
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9904261.html
Copyright © 2011-2022 走看看