查找和是某一值或者某一范围的的所有可能
2017-08-19 18:48
232 查看
昨天做笔试题,有这么一道题,稍有难度。
题目是:
输入包含多组数据。第一行为一个正整数T(T<=1000),表示测试数据的组数。然后是T组测试数据,每组测试数据占两行,第一行包/含两个整数n和m,表示ASCII码的范围。第二行为所使用的大写字
母的掩码,共26个数字构成的串,对应于26个大写字母,表示使用/对应字母的数量。输出对于每一组输入数据,输出一行"Case #k ans",
表示第k组数据的结果是ans。
样例输入
2
1 100
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
100 200
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
样例输出
Case #1: 3
Case #2: 4
Hint
说明:请注意严格按照格式进行输出,如 Case #1: 3(Case的C大写,冒号后有空格)第一组数据即A,B,C各一个的情况下,求ASCII和在1到100的组合,共有三组:即A(65),B(66),C(67);第二组在同等情况下求和在100到200范围内的组合,共四组,即AB(131),AC(132),BC
(133),ABC(198),其余交换字母位置的可能不考虑。
首先看一下第一种方法。用两个变量收缩走,但是这样无法讨论不连续的情况。
//没有考虑到不连续的情况
#define A 65
int Fun(vector<int> &ve,string &str,int i)
{
if(ve.size() < 1 || i < 0 || str.length() <= 0)
exit(1);
int small = ve[i*2];
int big = ve[i*2+1];
int start = 0;
int end = 0;
int max_cur = 0;
int max_i = 0;
while(end < str.length())
{
if(str[end] == '0')
{
end++;
continue;
}
max_cur += (end +++ A);
if(max_cur <= big && max_cur >= small)
{
max_i ++;
}
else if(max_cur < small)
continue;
else
{
max_cur -= (start +++ A);
}
}
max_cur -= (start +++ A);
while(max_cur <= big && max_cur >= small)
{
max_cur -= (start +++ A);
max_i ++;
}
return max_i;
}
int main()
{
int n;
vector<int> ve;
cin>>n;
string * str = new string
;
for(int i = 0; i < n; ++i)
{
int tmp;
cin>>tmp;
ve.push_back(tmp);
cin>>tmp;
ve.push_back(tmp);
cin>>str[i];
}
for(int i = 0; i < n; ++i)
{
int kn = Fun(ve,str[i],i);
cout<<"Case #"<<i+1<<": "<<kn<<endl;
}
return 0;
}这种情况有明显的缺点,但是我们可以有新情况,第二种情况是利用子集树来进行
代码如下:
#define A 65
void Fun(vector<int> &ve_tmp,int i,int len,int small,int big,int &num)
{
int sum = 0;
int k = 0;
while(i)
{
if(i & 1)
{
sum += ve_tmp[k];
}
k++;
i >>= 1;
}
if(sum >= small && sum <= big)
num++;
}
int Fun(vector<int> &ve,string &st,int i)
{
int small = ve[i * 2];
int big = ve[i * 2 + 1];
int num = 0;
vector<int> ve_tmp;
for(int i = 0; i < st.length(); ++i)
{
if(st[i] == '1')
{
ve_tmp.push_back(i + A);
}
}
int len = ve_tmp.size();
for(int i = 0; i < (1 << len); ++i)
{
Fun(ve_tmp,i,len,small,big,num);
}
return num;
}
int main()
{
int n;
vector<int> ve;
cin>>n;
string * str = new string
;
for(int i = 0; i < n; ++i)
{
int tmp;
cin>>tmp;
ve.push_back(tmp);
cin>>tmp;
ve.push_back(tmp);
cin>>str[i];
}
for(int i = 0; i < n; ++i)
{
int kn = Fun(ve,str[i],i);
cout<<"Case #"<<i+1<<": "<<kn<<endl;
}
return 0;
}
题目是:
输入包含多组数据。第一行为一个正整数T(T<=1000),表示测试数据的组数。然后是T组测试数据,每组测试数据占两行,第一行包/含两个整数n和m,表示ASCII码的范围。第二行为所使用的大写字
母的掩码,共26个数字构成的串,对应于26个大写字母,表示使用/对应字母的数量。输出对于每一组输入数据,输出一行"Case #k ans",
表示第k组数据的结果是ans。
样例输入
2
1 100
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
100 200
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
样例输出
Case #1: 3
Case #2: 4
Hint
说明:请注意严格按照格式进行输出,如 Case #1: 3(Case的C大写,冒号后有空格)第一组数据即A,B,C各一个的情况下,求ASCII和在1到100的组合,共有三组:即A(65),B(66),C(67);第二组在同等情况下求和在100到200范围内的组合,共四组,即AB(131),AC(132),BC
(133),ABC(198),其余交换字母位置的可能不考虑。
首先看一下第一种方法。用两个变量收缩走,但是这样无法讨论不连续的情况。
//没有考虑到不连续的情况
#define A 65
int Fun(vector<int> &ve,string &str,int i)
{
if(ve.size() < 1 || i < 0 || str.length() <= 0)
exit(1);
int small = ve[i*2];
int big = ve[i*2+1];
int start = 0;
int end = 0;
int max_cur = 0;
int max_i = 0;
while(end < str.length())
{
if(str[end] == '0')
{
end++;
continue;
}
max_cur += (end +++ A);
if(max_cur <= big && max_cur >= small)
{
max_i ++;
}
else if(max_cur < small)
continue;
else
{
max_cur -= (start +++ A);
}
}
max_cur -= (start +++ A);
while(max_cur <= big && max_cur >= small)
{
max_cur -= (start +++ A);
max_i ++;
}
return max_i;
}
int main()
{
int n;
vector<int> ve;
cin>>n;
string * str = new string
;
for(int i = 0; i < n; ++i)
{
int tmp;
cin>>tmp;
ve.push_back(tmp);
cin>>tmp;
ve.push_back(tmp);
cin>>str[i];
}
for(int i = 0; i < n; ++i)
{
int kn = Fun(ve,str[i],i);
cout<<"Case #"<<i+1<<": "<<kn<<endl;
}
return 0;
}这种情况有明显的缺点,但是我们可以有新情况,第二种情况是利用子集树来进行
代码如下:
#define A 65
void Fun(vector<int> &ve_tmp,int i,int len,int small,int big,int &num)
{
int sum = 0;
int k = 0;
while(i)
{
if(i & 1)
{
sum += ve_tmp[k];
}
k++;
i >>= 1;
}
if(sum >= small && sum <= big)
num++;
}
int Fun(vector<int> &ve,string &st,int i)
{
int small = ve[i * 2];
int big = ve[i * 2 + 1];
int num = 0;
vector<int> ve_tmp;
for(int i = 0; i < st.length(); ++i)
{
if(st[i] == '1')
{
ve_tmp.push_back(i + A);
}
}
int len = ve_tmp.size();
for(int i = 0; i < (1 << len); ++i)
{
Fun(ve_tmp,i,len,small,big,num);
}
return num;
}
int main()
{
int n;
vector<int> ve;
cin>>n;
string * str = new string
;
for(int i = 0; i < n; ++i)
{
int tmp;
cin>>tmp;
ve.push_back(tmp);
cin>>tmp;
ve.push_back(tmp);
cin>>str[i];
}
for(int i = 0; i < n; ++i)
{
int kn = Fun(ve,str[i],i);
cout<<"Case #"<<i+1<<": "<<kn<<endl;
}
return 0;
}
相关文章推荐
- HTTP 404。您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。
- 记录上锁(字节范围锁,特例:锁住文件的某一部分或者整个文件)
- 面试题[百度]--二叉排序树中查找和为某一值的所有路径
- grep技巧(-r):在某一目录下递归[所有子目录]查找某一字串:+文件路径
- 记录一次MVC 3.0错误 HTTP 404您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检查以下 URL 并确保其拼写正确。
- 【Shell】把某一文件夹下所有文件名或者路径存入TXT文档
- 二叉树中查找和为某一值的所有路径
- 30.查找所有可能的字符串组合
- 错误提示之(MVC3.0):HTTP 404。您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检查以下 URL 并确保其拼写正确。
- grep技巧(-r):在某一目录下递归[所有子目录]查找某一字串:+文件路径
- 查找 数据库中包含某一字段的所有表的表名的mysql语句
- find命令查找某一个时间点以后创建或者修改的文件
- 在linux下使用find命令查找某一个时间点以后创建或者修改的文件
- linux 系统 查找 某一进程 例如 java 进程 或者 tomcat 进程等
- Sqlserver中查找包含某一列的所有的表
- 使用BitSet查找某个范围内的所有的素数的个数(摘自java核心技术.卷I)
- C++实现查找二叉树中和为某一值的所有路径的示例
- grep技巧(-r):在某一目录下递归[所有子目录]查找某一字串:
- 无法运行宏,可能是因为该宏在此工作簿中不可用,或者所有的宏都被禁用的解决方法
- 错误提示之(MVC3.0):HTTP 404。您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检查以下 URL 并确保其拼写正确 MVC误设起始页