bzoj1028 [JSOI2007]麻将
1028: [JSOI2007]麻将
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 1337 Solved: 601
[Submit][Status][Discuss]
Description
麻将是中国传统的娱乐工具之一。麻将牌的牌可以分为字牌(共有东、南、西、北、中、发、白七种)和序数牌(分为条子、饼子、万子三种花色,每种花色各有一到九的九种牌),每种牌各四张。在麻将中,通常情况下一组和了的牌(即完成的牌)由十四张牌组成。十四张牌中的两张组成对子(即完全相同的两张牌),剩余的十二张组成三张一组的四组,每一组须为顺子(即同花色且序数相连的序数牌,例如条子的三、四、五)或者是刻子(即完全相同的三张牌)。一组听牌的牌是指一组十三张牌,且再加上某一张牌就可以组成和牌。那一张加上的牌可以称为等待牌。 在这里,我们考虑一种特殊的麻将。在这种特殊的麻将里,没有字牌,花色也只有一种。但是,序数不被限制在一到九的范围内,而是在1到n的范围内。同时,也没有每一种牌四张的限制。一组和了的牌由3m + 2张牌组成,其中两张组成对子,其余3m张组成三张一组的m组,每组须为顺子或刻子。现给出一组3m + 1张的牌,要求判断该组牌是否为听牌(即还差一张就可以和牌)。如果是的话,输出所有可能的等待牌。
Input
包含两行。第一行包含两个由空格隔开整数n, m (9<=n<=400, 4<=m<=1000)。第二行包含3m + 1个由空格隔开整数,每个数均在范围1到n之内。这些数代表要求判断听牌的牌的序数。
Output
输出为一行。如果该组牌为听牌,则输出所有的可能的等待牌的序数,数字之间用一个空格隔开。所有的序数必须按从小到大的顺序输出。如果该组牌不是听牌,则输出"NO"。
Sample Input
1 1 2 2 3 3 5 5 5 7 8 8 8
Sample Output
HINT
Source
题意:很好懂,前面麻将的介绍基本不用看
精简后的题意
刻子(即完全相同的三张牌 顺子(序数相连的牌,例如三、四、五) 对子(即完全相同的两张牌
序数在1到n的范围内。每一种牌张数无限制。
一组和牌由3m + 2张牌组成,其中两张组成对子,其余3m张组成三张一组的m组,每组须为顺子或刻子。
现给出一组3m + 1张的牌,要求判断该组牌是否为听牌(即还差一张就可以和牌)。如果是的话,输出所有可能的等待牌。
分析:首先看到 n<=400
那么我们会想到的是枚举要加进哪张牌(毕竟要输出的是每一种方案而不是方案数)
那加进之后如何检验。。。。。
我们这样想问题 -> 数字为i的牌只能与 i+1, i+2组成顺子,而不考虑与i-1,i-2组成顺子(即规定一个方向,以免重复和为了下面叙述方便)
那么数字为n-1,n的牌一定要是若干个刻子(在抽走了组成了顺子的牌之后)
那么显然至少有(a[n]%3)个顺子
若顺子的个数大于等于3,即3*k+x个i,i+1,i+2这样个顺子,那么可以当成k个i的刻子和k个i+1的刻子和k个i+2的刻子以及x个顺子(x<3)
所以可以证明倒着枚举数字,优先安排刻子的,其次安排顺子的贪心顺序是正确的
当然正着枚举也是一样的道理
听说这题有dp做法,我得好好想想,不过在网上找不到
这是倒着枚举的代码,其实正着枚举要简单写(其实两代码一样)
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <ctime>
using namespace std;
typedef long long LL;
typedef double DB;
#define For(i, s, t) for(int i = (s); i <= (t); i++)
#define Ford(i, s, t) for(int i = (s); i >= (t); i--)
#define Rep(i, t) for(int i = (0); i < (t); i++)
#define Repn(i, t) for(int i = ((t)-1); i >= (0); i--)
#define rep(i, x, t) for(int i = (x); i < (t); i++)
#define MIT (2147483647)
#define INF (1000000001)
#define MLL (1000000000000000001LL)
#define sz(x) ((int) (x).size())
#define clr(x, y) memset(x, y, sizeof(x))
#define puf push_front
#define pub push_back
#define pof pop_front
#define pob pop_back
#define ft first
#define sd second
#define mk make_pair
inline void SetIO(string Name) {
string Input = Name+".in",
Output = Name+".out";
freopen(Input.c_str(), "r", stdin),
freopen(Output.c_str(), "w", stdout);
} const int N = ;
int n, m, Arr[N];
int Ans[N], Tot; inline void Input() {
scanf("%d%d", &n, &m);
For(i, , *m+) {
int x;
scanf("%d", &x);
Arr[x]++;
}
} int Tmp[N];
inline bool Check(int x) {
For(i, , n) {
For(j, , n) Tmp[j] = Arr[j];
Tmp[x]++;
Tmp[i] -= ;
if(Tmp[i] < ) continue; bool flag = ;
Ford(j, n, ) {
if(Tmp[j] < ) {
flag = ;
break;
}
if(!Tmp[j]) continue;
Tmp[j] %= ;
Tmp[j-] -= Tmp[j];
Tmp[j-] -= Tmp[j];
Tmp[j] = ;
}
Tmp[] %= , Tmp[] %= ;
if(Tmp[] || Tmp[]) flag = ; if(flag) return ;
}
return ;
} inline void Solve() {
For(i, , n)
if(Check(i)) Ans[++Tot] = i; if(!Tot) puts("NO");
else {
For(i, , Tot-) printf("%d ", Ans[i]);
printf("%d\n", Ans[Tot]);
}
} int main() {
#ifndef ONLINE_JUDGE
SetIO("");
#endif
Input();
Solve();
return ;
}
这是正着枚举
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <ctime>
using namespace std;
typedef long long LL;
typedef double DB;
#define For(i, s, t) for(int i = (s); i <= (t); i++)
#define Ford(i, s, t) for(int i = (s); i >= (t); i--)
#define Rep(i, t) for(int i = (0); i < (t); i++)
#define Repn(i, t) for(int i = ((t)-1); i >= (0); i--)
#define rep(i, x, t) for(int i = (x); i < (t); i++)
#define MIT (2147483647)
#define INF (1000000001)
#define MLL (1000000000000000001LL)
#define sz(x) ((int) (x).size())
#define clr(x, y) memset(x, y, sizeof(x))
#define puf push_front
#define pub push_back
#define pof pop_front
#define pob pop_back
#define ft first
#define sd second
#define mk make_pair
inline void SetIO(string Name) {
string Input = Name+".in",
Output = Name+".out";
freopen(Input.c_str(), "r", stdin),
freopen(Output.c_str(), "w", stdout);
} const int N = ;
int n, m, Arr[N];
int Ans[N], Tot; inline void Input() {
scanf("%d%d", &n, &m);
For(i, , *m+) {
int x;
scanf("%d", &x);
Arr[x]++;
}
} int Tmp[N];
inline bool Check(int x) {
For(i, , n) {
For(j, , n+) Tmp[j] = Arr[j];
Tmp[x]++;
Tmp[i] -= ;
if(Tmp[i] < ) continue; bool flag = ;
For(j, , n+) {
if(Tmp[j] < ) {
flag = ;
break;
}
if(!Tmp[j]) continue;
Tmp[j] %= ;
Tmp[j+] -= Tmp[j];
Tmp[j+] -= Tmp[j];
Tmp[j] = ;
}
if(flag) return ;
}
return ;
} inline void Solve() {
For(i, , n)
if(Check(i)) Ans[++Tot] = i; if(!Tot) puts("NO");
else {
For(i, , Tot-) printf("%d ", Ans[i]);
printf("%d\n", Ans[Tot]);
}
} int main() {
#ifndef ONLINE_JUDGE
SetIO("");
#endif
Input();
Solve();
return ;
}
//-------------------------------------------------------
大概是想出来如何dp了,不过比较麻烦,但复杂度较低
先是枚举加入的数字,然后dp求解
dp[2][400][1000][1000][1000]
第一位表示是否选择了对子,第二位表示当前进行到了第个数字(设为第x个数字),第三位-第五位表示从第x,x+1,x+2个数字的个数
显然有效状态很少,我们可以用队列和Hash实现这个dp过程
转移时对于每一个状态的转移参考那个优先刻子,其次顺子的贪心策略,推到下一个状态
整个过程的复杂度应该是O(n^2)
听说还有O(n)的dp做法,我再想想
bzoj1028 [JSOI2007]麻将的更多相关文章
- bzoj千题计划118:bzoj1028: [JSOI2007]麻将
http://www.lydsy.com/JudgeOnline/problem.php?id=1028 枚举等待牌 枚举对是哪个 判断 #include<cstdio> #include ...
- 【BZOJ1028】[JSOI2007]麻将(贪心)
[BZOJ1028][JSOI2007]麻将(贪心) 题面 BZOJ 洛谷 题解 感觉好久没打过麻将了,似乎都快不会打了. 这个数据范围看着就觉得是\(O(n^2m)\). 那么就枚举听哪张牌,然后枚 ...
- BZOJ 1028: [JSOI2007]麻将 暴力
1028: [JSOI2007]麻将 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/prob ...
- BZOJ 1028 [JSOI2007]麻将
1028: [JSOI2007]麻将 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1270 Solved: 576[Submit][Status][ ...
- 1028: [JSOI2007]麻将
1028: [JSOI2007]麻将 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2638 Solved: 1168[Submit][Status] ...
- [JSOI2007]麻将 模拟 BZOJ1028
题目描述 麻将是中国传统的娱乐工具之一.麻将牌的牌可以分为字牌(共有东.南.西.北.中.发.白七种)和序数牌(分为条子.饼子.万子三种花色,每种花色各有一到九的九种牌),每种牌各四张. 在麻将中,通常 ...
- 【bzoj1028】[JSOI2007]麻将
首先枚举等待牌,再枚举对子牌. 然后1~n扫一遍,如果现在 s[i]不能被3整除,那么必须跟后两个数搭配几下变成能被3整除的.然后如果能被3整除,那么只要三个连续的一组可行,则三个相同的一组必定也 ...
- 1028: [JSOI2007]麻将 - BZOJ
Description 麻将是中国传统的娱乐工具之一.麻将牌的牌可以分为字牌(共有东.南.西.北.中.发.白七种)和序数牌(分为条子.饼子.万子三种花色,每种花色各有一到九的九种牌),每种牌各四张.在 ...
- [JSOI2007]麻将
Description 麻将是中国传统的娱乐工具之一.麻将牌的牌可以分为字牌(共有东.南.西.北.中.发.白七种)和序数 牌(分为条子.饼子.万子三种花色,每种花色各有一到九的九种牌),每种牌各四张. ...
随机推荐
- OpenGL顶点缓冲区对象(VBO)
转载 http://blog.csdn.net/dreamcs/article/details/7702701 创建VBO GL_ARB_vertex_buffer_object 扩展可 ...
- 重新编译安装gcc-4.1.2(gcc版本降级)之TFS安装
wget http://gcc.parentingamerica.com/releases/gcc-4.1.2/gcc-4.1.2.tar.gz tar -zxfv gcc-4.1.2.tar.gz ...
- Maximum Product Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest ...
- python操作Excel读写--使用xlrd
一.安装xlrd模块 到python官网下载http://pypi.python.org/pypi/xlrd模块安装,前提是已经安装了python 环境. 二.使用介绍 1.导入模块 import x ...
- iOS UITableView 的beginUpdates和endUpdates
在官方文档中是这样介绍beginUpdates的 Call this method if you want subsequent insertions, deletion, and selection ...
- Java for LeetCode 191 Number of 1 Bits
Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also know ...
- Java for LeetCode 187 Repeated DNA Sequences
All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...
- 中石油—2的幂次方(power)
问题 E: 2的幂次方(power) 时间限制: 1 Sec 内存限制: 64 MB提交: 38 解决: 19[提交][状态][讨论版] 题目描述 任何一个正整数都可以用2的幂次方表示.例如:13 ...
- BestCoder9 1003 Revenge of kNN(hdu 4995) 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4995 题目意思:在一个一维坐标轴上,给出位置 xi 和值 vi,对于 M 次询问,每次询问给出inde ...
- springMVC获取file,几种转换
//从前台通过name值获取file MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)reque ...