5-1 Where is the Marble? uva10474
题意:在一排数中查询某个数的位置。
思路:运用STL算法库sort,lower_bound().(查找大于等于x的第一个位置),
#include
using namespace std;
const int maxn=10100;
int a[maxn];
int main()
{
int n,q,t=0;
while(cin>>n>>q)
{
if(!n&&!q) break;
cout<<"CASE# "<<++t<<":"<for(int i=0;icin>>a[i];
sort(a,a+n);
while(q--)
{
int x;cin>>x;
int pos=lower_bound(a,a+n,x)-a;
if(a[pos]==x) cout<" found at "<1<else cout<" not found"<
5-2 The Blocks Problem uva101
题意:从左到右,有1~n个木块,模拟四种操作。
move a onto b;move a over b;pile a onto b;pile a over b;
思路:由于每个数组长度变化,不定长,正好运用vector.
找出四种操作的共性与差异 ,move 与pile差别就是,要不要把a所在堆上方木块归位。onto 与 over 差别是要不要把 b上面的归位。
这样,总结 这四种操作,我们只用写三个函数,find(int a,int &p,int &h)找到a所在堆的位置,以及他在这个堆高度。clear_above(int p,int h)将p堆h高度以上的木块归位。pile_onto(int p,int h,int p2)将p堆h高度以上木块落在p2堆上。
#include
#include
#include
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=30;
int inf=0x3f3f3f3f;
LL mod=1e9+7;
vector<int>pile[N];
int n;
void find_block(int a,int &p,int &h)
{
for(p=0;pfor(h=0;hif(a==pile[p][h]) return;
}
void clear_above(int p,int h)
{
for(int i=h+1;i1);
}
void pile_onto(int pa,int ha,int pb)
{
for(int i=ha;ivoid print()
{
for(int i=0;iprintf("%d:",i);
for(int j=0;jprintf(" %d",pile[i][j]);
printf("\n");
}
}
int main()
{
while(~scanf("%d",&n))
{
int a,b;
string s1,s2;
for(int i=0;iwhile(cin>>s1)
{
//cout<
if(s1=="quit") break;
cin>>a>>s2>>b;
int pa,pb,ha,hb;
find_block(a,pa,ha);
find_block(b,pb,hb);
if(pa==pb) continue;
if(s1=="move") clear_above(pa,ha);
if(s2=="onto") clear_above(pb,hb);
pile_onto(pa,ha,pb);
}
cout<<"ok"<
5-3 Andy’s First Dictionary uva10815
题意:输入一段字符串,让你找出所有不重复的单词,不区分大小写,按照字典序从小到大输出。
思路:直接的思路,不区分大小写,就先将所有字符统一成小写,学习运用stl 里set 可以去重的用法,同时set里面元素是有序的,还有个技巧,利用string,stringstream分割每行的字符串。
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1000005;
int inf=0x3f3f3f3f;
LL mod=1e9+7;
set<string>dict;
int main()
{
string s,buf;
while(getline(cin,s))
{
for(int i=0;iif(isalpha(s[i])) s[i]=tolower(s[i]);else s[i]=' ';
stringstream ss(s);
while(ss>>buf) dict.insert(buf);
}
for(set<string>::iterator iter=dict.begin();iter!=dict.end();++iter)
cout<<*iter<return 0;
}
5-4 uva156 Ananagrams
题意:输入几行字符串,找到满足每个字母重新排列后都没有重复的单词,也不区分大小写,并按照字典序输出。
思路,由于每个单词要求重新排列后都不同,将他们排序小写化统一后,与出现次数建立一个映射关系,出现次数等于1 就满足。
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1000005;
int inf=0x3f3f3f3f;
LL mod=1e9+7;
string trans(string s)
{
string ans=s;
for(int i=0;itolower(ans[i]);
sort(ans.begin(),ans.end());
return ans;
}
int main()
{
string s;
vector<string>words;
map<string,int>cnt;
while(cin>>s)
{
string temp;
if(s[0]=='#') break;
words.push_back(s);
temp=trans(s);
if(!cnt.count(temp)) cnt[temp]=0;
cnt[temp]++;
}
vector<string>ans;
for(int i=0;iif(cnt[trans(words[i])]==1) ans.push_back(words[i]);
sort(ans.begin(),ans.end());
for(int i=0;icout<return 0;
}
5-5 uva12096 The SetStack Computer
题意及思路:本题描述很高大上,其实最重要发现模拟过程中栈里存的是什么,一般认为栈里的元素不是整数变量或是字符串变量,而这里是集合,因为ADD操作特性是把栈顶出栈后当做元素放在下一个出栈的集合里,构成新的集合再入栈。所以这个集合就可以用set模拟,int表示每个元素的给他制定一个独一无二ID,还可以达到去重的功能。在判断这个元素ID是否已经存在,则又需要一个map《set《int》,int》”映射每一个存在的。详细模拟见代码。
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1000005;
int inf=0x3f3f3f3f;
LL mod=1e9+7;
stack< set<int> >stk;
map<set<int>,int>mp;
//vector >Id;
set<int>s1,s2;
int num;
set<int> ID(set<int> x)
{
if(mp.count(x)) return x;
mp[x]=num++;
return x;
}
void pop()
{
s1=stk.top(); stk.pop();
s2=stk.top(); stk.pop();
}
void push()
{
set<int>s;
stk.push(ID(s));
}
void dup()
{
set<int>s=stk.top();
stk.push(s);
}
void Union()
{
pop();
set<int>::iterator it;
for(it=s1.begin();it!=s1.end();it++)
s2.insert(*it);
stk.push(ID(s2));
}
void Intersect()
{
pop();
set<int>s3;
for(set<int>::iterator it=s1.begin();it!=s1.end();it++)
if(s2.find(*it)!=s2.end()) s3.insert(*it);
stk.push(ID(s3));
}
void add()
{
pop();
s2.insert(mp[s1]);
stk.push(ID(s2));
}
int main()
{
int T;cin>>T;
while(T--)
{
int n;cin>>n;
string s;
num=0;
mp.clear();
while(!stk.empty()) stk.pop();
s1.clear();s2.clear();
for(int i=0;icin>>s;
if(s[0]=='P') push();
else if(s[0]=='D') dup();
else if(s[0]=='U') Union();
else if(s[0]=='I') Intersect();
else if(s[0]=='A') add();
cout<cout<<"***"<
刘大神实现并集,交集借用了set自带set_union,set_intersection函数,代码量简化很多。还有一点不同是,刘大神stack《int》里存的是每个集合的ID。多加一个vector《set《int》》,方便找每个set《int》 ID.
#include
using namespace std;
typedef set<int> Set;
mapint >mp;
vector Id;
int ID(Set x)
{
if(mp.count(x)) return mp[x];
Id.push_back(x);
return mp[x]=Id.size()-1;
}
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
int main()
{
int T;cin>>T;
while(T--)
{
int n;cin>>n;
stack<int>stk;
while(n--)
{
string s;
cin>>s;
if(s[0]=='P') stk.push(ID(Set()));
else if(s[0]=='D') stk.push(stk.top());
else
{
Set x1=Id[stk.top()];stk.pop();
Set x2=Id[stk.top()];stk.pop();
Set x;
if(s[0]=='U') set_union(ALL(x1),ALL(x2),INS(x));
if(s[0]=='I') set_intersection(ALL(x1),ALL(x2),INS(x));
if(s[0]=='A') {x=x2;x.insert(ID(x1));}
stk.push(ID(x));
}
cout<cout<<"***"<
5-6 uva540 TeamQueue
题意:有t个人排队,每次来一个人,如果有他的队友在排队,那么这个人就会插到他队友最后的位置。输出这个队伍,排队情况。
利用两个队列,第一个表示不同团体在整个队列的顺序情况,第二个表示每个个体在不同团体中情况,要用一个数组队列,表示第几个团体的队列。还需要一个个体对应团体的映射map《int,int》。
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1005;
int inf=0x3f3f3f3f;
LL mod=1e9+7;
int main()
{
int t,cnt=0;;
while(cin>>t&&t)
{
cout<<"Scenario #"<<++cnt<map<int,int>team;
for(int i=0;iint n;cin>>n;
for(int j=0;jint x;cin>>x;
team[x]=i;
}
}
queue<int>q,q2[N];//q是团体的在整个队列先后顺序,q2表示每个团体里面队列情况
for(;;)
{
string s; cin>>s;
if(s[0]=='S') break;
if(s[0]=='D')
{
int a=q.front();
cout<if(q2[a].empty()) q.pop();
}
else if(s[0]=='E')
{
int num; cin>>num;
if(q2[team[num]].empty()) q.push(team[num]);
q2[team[num]].push(num);
}
}
cout<
5-7 uva 136 Ugly Number
题意:丑数是指不能被2 3 5以外的其他素数整除的数。把丑数从小到大排列起来: 1,2,3,4,5,6,8,9,10,12,…..求第1500个丑数是?
本题实现方法还有很多:最容易想到就是利用优先队列,加set判断,去重。如下。
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1000005;
int inf=0x3f3f3f3f;
LL mod=1e9+7;
const LL coeff[3]={2,3,5};
int main()
{
set s; s.clear();
priority_queuevector,greater >q;
s.insert(1);q.push(1);
for(int i=1;;i++)
{
LL x=q.top();q.pop();
if(i==1500)
{
cout<<"The 1500'th ugly number is "<break;
}
for(int j=0;j<3;j++)
{
LL x2=x*coeff[j];
if(!s.count(x2)) {s.insert(x2),q.push(x2);}
}
}
return 0;
}
5-8 uva 400 Unix is
题意:给你n个字符串,左对齐的方式,按列优先以每六十个单位为一行输出所有字符串,每列之间的距离是所有字符串中最长的长度的加二,最后一列之后没有空格。
思路,输入字符串的时候记录最长长度,先算一行有多少列,根据总个数算多少行,输出。考察模拟代码工地,有一个技巧,这里重复实现将一个字符串输出后,再输出空格的功能,所以编写一个函数,极大简化代码。
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=110;
int inf=0x3f3f3f3f;
LL mod=1e9+7;
string s[N];
void print(const string &s,int len,char extra)
{
cout<for(int i=0;icout<int main()
{
int n;
while(cin>>n)
{
int maxx=0;
for(int i=0;icin>>s[i];
maxx=max(maxx,(int)s[i].length());
}
int cols=62/(maxx+2),row=(n-1)/cols+1;
sort(s,s+n);
print("",60,'-');
cout<for(int i=0;ifor(int j=0;jint idx=j*row+i;
if(idx1?maxx:maxx+2,' ');
}
cout<
5-9 uva 1592 Database
题意 :给一个n行m列字符串,问你是否存在两个不同行r1,r2,两个不同列c1,c2,使得 (r1,c1),(r2,c1)与(r1,c2),(r2,c2)相等。
直接写一个四重枚举,10000*10000*10*10绝壁TLE。
解决方法:这里有个技巧,判断字符串是否相同需要时间比较长,我们就先把每个位置字符串先预处理对应成数字编号,map《string,int》判重,给他赋编号,就构建一个n行m列的整数数组。
先枚举c1,c2,两列,然后从上往下扫描,每碰到一个新的行r,把它的两列,作为一个二元组,放入map《pair《int ,int 》,int》,左边赋值n行m列位置的编号,右边赋值这个编号所处的行位置,如果有重复的,就说明从c1,c2两列的的这两行相同,直接输出结果。
复杂度:10*10*10000 不会超时。
#include
#include
#include
#include
#include
using namespace std;
const int N=10010,M=20;
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
getchar();
map<string, int>dict;
char entry[110],coma;
int db[N][M],cnt=1;
for(int i=0;ifor(int j=0;j1;j++)
{
scanf("%[^,]%c",entry,&coma);
string s(entry);
if(!dict.count(s)) dict[s]=cnt++;
db[i][j]=dict[s];
}
scanf("%[^\n]",entry);
getchar();
string s(entry);
if(!dict.count(s)) dict[s]=cnt++;
db[i][m-1]=dict[s];
}
int ok=0;
for(int c1=0;c1for(int c2=c1+1;c2mapint,int>, int>vis;
for(int r2=0;r2int,int>p(db[r2][c1],db[r2][c2]);
if(vis.count(p))
{
ok=1;
printf("NO\n%d %d\n %d %d\n",vis[p]+1,r2+1,c1+1,c2+1);
break;
}
vis[p]=r2;
}
if(ok) break;
}
if(ok) break;
}
if(!ok) printf("YES\n");
}
return 0;
}
(未完)
后记:暂时先补充这些题解,加深巩固,这一章后面还做了几道习题,题很好,但由于没有时间了…..(还有一堆别的作业,机组卷子,机组实验,概率论卷子,数据结构卷子,TM这些还都要期中考试,数据结构的几个算法,笔试卷子题也没练习过).这段时间要反思一下时间都去哪呢(打炉石)..我会说开学到现在就陆陆续续水了这点东西…
今天下午传来一个好消息,组长田博士亚洲区现场赛两枚铜牌,还有一场可惜银牌!!!!(恭喜学长)