忽略花色, 每种牌数量无限. 顺子是序数相连的三张牌, 刻子是序数相同的三张牌, 对子是序数相同的两张牌. 一组和了的牌由(3m+2)张牌组成: 一个对子, 其余每3张一组, 每组是顺子或刻子. 听牌是还差一张就可以和的牌. 判断某组牌是否是听牌, 如果是, 从小到大输出所有可能的等待牌. (9≤n≤400, 4≤m≤1000) n≤400, 不妨枚举等待牌, 判断是否和了. 判断牌是否和了, 可以枚举一下对子, 判断剩下的牌是否能分成合法的m组. 数据规模不允许DP. 贪心的话, 不管是先找出所有的顺子, 还是先找出所有的刻子, 都举出了反例......
题解说, 扫一遍, 对于每种牌, 先考虑刻子, 再考虑和后面的牌组成顺子.
不妨设序数最小的牌是1, 共x张. 如果能和, 考虑一种方案: a张组成刻子, b张和后面的2,3组成顺子. 这说明, 2,3也至少各有b张. 不妨把(b-b mod 3)张1,2,3换成刻子. 对所有的顺子均进行这样的操作. 可以看到 (脑补一下), 改造后的方案就是我们的贪心算法所得到的.
这类的贪心我也不知道该怎么对付...... TAT
斯里尼瓦瑟·拉马努金(泰米尔语:ஸ்ரீனிவாஸ ராமானுஜன் ஐயங்கார்,转写:Srīṉivāsa Rāmāṉujan Aiyaṅkār,又译拉马努詹,1887年12月22日-1920年4月26日)是印度历史上最著名的数学家之一。
他没受过正规的高等数学教育,沉迷数论,尤爱牵涉π、质数等数学常数的求和公式,以及整数分拆。惯以直觉(或者是跳步)导出公式,不喜作证明(事后往往证明他是对的)。他留下的那些没有证明的公式,引发了后来的大量研究。
培养直觉?
#define x first
#define y second
const int N = 400;
int a[N+3], b[N+3];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
rep (_, 0, 3*m+1) {
int i;
scanf("%d", &i);
++a[i];
}
int cnt = 0;
rep (i, 1, n+1) {
bool ok = false;
++a[i];
rep (j, 1, n+1) if (a[j] >= 2) {
bool flag = true;
copy(a+1, a+n+1, b+1);
b[j] -= 2;
rep (k, 1, n+1) {
b[k] %= 3;
if (b[k]) {
int t = min(b[k], min(b[k+1], b[k+2]));
b[k] -= t, b[k+1] -= t, b[k+2] -= t;
if (b[k]) {
flag = false;
break;
}
}
}
if (flag) {
ok = true;
break;
}
}
--a[i];
if (ok) {
if (cnt++) putchar(' ');
printf("%d", i);
}
}
if (!cnt) printf("NO");
puts("");
return 0;
}