一天得做洛谷十题,是可完成的,因为大学没什么作业。计划start
这题目这么水,我依旧不会,可以见到我弱到没有边了。水平实在太垃圾了,赶紧做。
单词接龙
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beastbeast和astonishastonish,如果接成一条龙则变为beastonishbeastonish,另外相邻的两部分不能存在包含关系,例如atat 和 atideatide 间不能相连。
输入输出格式
输入格式:
输入的第一行为一个单独的整数nn (n \le 20n≤20)表示单词数,以下nn 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出格式:
只需输出以此字母开头的最长的“龙”的长度
输入输出样例
输入样例#1: 复制
5
at
touch
cheat
choose
tact
a
输出样例#1: 复制
23
#include<bits/stdc++.h>
using namespace std;
char ch;
int n;
string s[30];//the use of string
int jie[30][30];
int vis[30];
int an=0;int ans=-1;
int pre(int i,int j){
int sy=0;
bool xy=true;//注意最小重合
for(int k=s[i].size()-1;k>=0;k--){
for(int kx=k;kx<s[i].size();kx++){
if(s[i][kx]!=s[j][sy++]){
xy=false;
break;
}
}
sy=0;//初值小心
if(xy) {
return s[i].size()-k;
}
xy=true;//
}
return 0;
}
void dfs(int p){
bool flag=false;//fangzai 外面
for(int i=1;i<=n;i++){
//连接成功为true
if(vis[i]>=2) continue;
if(jie[p][i]==s[i].size()||jie[p][i]==s[p].size()){
continue;
}
if(jie[p][i]==0) continue;
flag=true;
vis[i]++;
an+=s[i].size()-jie[p][i];//回溯
dfs(i);
vis[i]--;
an-=s[i].size()-jie[p][i];
}
if(!flag) ans=max(ans,an); //放在外循环
return ;
}
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i];
}
cin>>ch;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
jie[i][j]=pre(i,j);
}
}
//int ans=-1;
for(int i=1;i<=n;i++){
if(ch==s[i][0]){
an=s[i].size(); //更新长度
vis[i]++;
dfs(i);
vis[i]=0;//
}
}
cout<<ans<<endl;
return 0;
}
//关键是那个前后包含的话,我没想出实现方法,感觉很玄学,实际上,数据比较小的话,一个个试就行了,写个函数。
emmm,要重合最小,所以从后面开始。
题目描述
输入b,p,k的值,求b^p mod k的值。其中b,p,k*k为长整型数。
输入输出格式
输入格式:
三个整数b,p,k.
输出格式:
输出“b^p mod k=s”
s为运算结果
输入输出样例
输入样例#1: 复制
2 10 9
输出样例#1: 复制
2^10 mod 9=7
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
ll n,k,p;
cin>>n>>k>>p;
ll a,b,res;res=1;
a=n;
b=k;
while(b)
{
//res%=p;
if(b%2==1) res*=a,res%=p;
a*=a;a%=p;
b>>=1;
//cout<<res<<"Fe"<<a<<endl;
}
// cout<<res<<endl;
res%=p;//少了这一句就错了
cout<<n<<"^"<<k<<" mod "<<p<<"="<<res;
return 0;
}
特殊数据:2 的0次方,%1=0.
幂次方
题目描述
任何一个正整数都可以用22的幂次方表示。例如
137=2^7+2^3+2^0137=27+23+20
同时约定方次用括号来表示,即a^bab 可表示为a(b)a(b)。
由此可知,137137可表示为:
2(7)+2(3)+2(0)2(7)+2(3)+2(0)
进一步:
7= 2^2+2+2^07=22+2+20(2^1用2表示),并且
3=2+2^03=2+20
所以最后137137可表示为:
2(2(2)+2+2(0))+2(2+2(0))+2(0)2(2(2)+2+2(0))+2(2+2(0))+2(0)
又如:
1315=2^{10} +2^8 +2^5 +2+11315=210+28+25+2+1
所以13151315最后可表示为:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
输入输出格式
输入格式:
一个正整数n(n≤20000)n(n≤20000)。
输出格式:
符合约定的nn的0,20,2表示(在表示中不能有空格)
输入输出样例
输入样例#1: 复制
1315
输出样例#1: 复制
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
#include<bits/stdc++.h>
using namespace std;
int cc[17]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536};
void check(int n){
if(n==1) {
return;}
if(n==2) {
cout<<"2";return;}
if(n==0) cout<<0;
for(int i=16;i>=0;i--){
if(n>=cc[i])
{
cout<<2;
if(i!=1) cout<<"(";
check(i);
// cout<<i;
if((i)!=1) cout<<")";
//cout<<")";
n-=cc[i];
if(n!=0) cout<<"+";
}
if(n==0) {
//cout<<0;
return ;
}
}
}
int main(){
int n;
cin>>n;int i=1;
check(n);
return 0;
}
有范围,且模拟,改了好久,基础薄弱,题解看的心累,于是留待以后。
题目描述
猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
Update:数据已加强。
输入输出格式
输入格式:
第一行,一个数n,表示序列中有n个数。
第二行n个数,表示给定的序列。序列中每个数字不超过10^9109
输出格式:
给定序列中逆序对的数目。
输入输出样例
输入样例#1: 复制
6
5 4 2 6 3 1
输出样例#1: 复制
11
说明
对于25%的数据,n \leq 2500n≤2500
对于50%的数据,n \leq 4 \times 10^4n≤4×104。
对于所有数据,n \leq 5 \times 10^5n≤5×105
请使用较快的输入输出
应该不会n方过50万吧 by chen_zhe
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll ans =0;
int a[500010];
int an[500010];
void gui(int l,int r){
if(l>=r) return;
int mid=(l+r)>>1;
gui(l,mid);gui (mid+1,r);
int k=mid+1;int y=0;
for(int i=l;i<=mid||k<=r;){//边界问题
if(i>mid) an[y++]=a[k++];
else if(k>r) an[y++]=a[i++];//else
else if(a[i]>a[k])
ans+=mid-i+1,an[y++]=a[k++];
else an[y++]=a[i++];
}
for(int j=0;j<y;j++){//复制问题
a[l+j]=an[j];
}
return ;
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
gui(1,n);
cout<<ans<<endl;
return 0;
}
自己写过的果然就是顺。
分形就是自相似,
南蛮图腾
自从到了南蛮之地,孔明不仅把孟获收拾的服服帖帖,而且还发现了不少少数民族的智慧,他发现少数民族的图腾往往有着一种分形的效果,在得到了酋长的传授后,孔明掌握了不少绘图技术,但唯独不会画他们的图腾,于是他找上了你的爷爷的爷爷的爷爷的爷爷……帮忙,作为一个好孙子的孙子的孙子的孙子……你能做到吗?
输入输出格式
输入格式:
每个数据一个数字,表示图腾的大小(此大小非彼大小) n<=10
输出格式:
这个大小的图腾
输入输出样例
输入样例#1: 复制
2
输出样例#1: 复制
/\
/__\
/\ /\
/__\/__\
输入样例#2: 复制
3
输出样例#2: 复制
/\
/__\
/\ /\
/__\/__\
/\ /\
/__\ /__\
/\ /\ /\ /\
/__\/__\/__\/__\
#include<bits/stdc++.h>
using namespace std;
char a[1025][2049];//范围
int main(){
int n;
cin>>n;
for(int i=0;i<=1024;i++)
for(int j=0;j<=2048;j++){
a[i][j] =' ';//要是不赋初值默认为null,可能报错
}
int length=4;int k=1;
a[0][0]=a[1][1]='/';
a[0][2]=a[0][1]='_';
a[0][3]=a[1][2]='\\';
while(k<n){
for(int i=0;i<length/2;i++)
for(int j=0;j<length;j++){
a[i+length/2][j+length/2]=a[i][j+length]=a[i][j];
}
k++;
length*=2;
}
for(int i=(length/2)-1;i>=0;i--){
for(int j=0;j<length;j++) {
cout<<a[i][j];
}
cout<<endl;
}
return 0;
}
图要会倒过来复制,正过来位置变动不好弄,输出的时候要反过来,也就是说,存的时候也要反过来。
导弹拦截
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是\le 50000≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出格式
输入格式:
11行,若干个整数(个数\le 100000≤100000)
输出格式:
22行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出样例
输入样例#1: 复制
389 207 155 300 299 170 158 65
输出样例#1: 复制
6
2
说明
为了让大家更好地测试n方算法,本题开启spj,n方100分,nlogn200分
每点两问,按问给分
对于问二求整个数列的最长上升子序列即可。证明如下:
(1)假设打导弹的方法是这样的:取任意一个导弹,从这个导弹开始将能打的导弹全部打完。而这些导弹全部记为为同一组,再在没打下来的导弹中任选一个重复上述步骤,直到打完所有导弹。
(2)假设我们得到了最小划分的K组导弹,从第a(1<=a<=K)组导弹中任取一个导弹,必定可以从a+1组中找到一个导弹的高度比这个导弹高(因为假如找不到,那么它就是比a+1组中任意一个导更高,在打第a组时应该会把a+1组所有导弹一起打下而不是另归为第a+1组),同样从a+1组到a+2组也是如此。那么就可以从前往后在每一组导弹中找一个更高的连起来,连成一条上升子序列,其长度即为K;
(3)设最长上升子序列长度为P,则有K<=P;又因为最长上升子序列中任意两个不在同一组内(否则不满足单调不升),则有
P>=K,所以K=P。
这个的话细致想想还是可以的,也就是说在熟练的基础上,但我基础真是薄弱,挺难发散思维的吧。
由于涉及的知识比较多,所以要有着重点地去看,知识点写到word文档里去了。
题目描述
每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括99位数字、11位识别码和33位分隔符,其规定格式如x-xxx-xxxxx-x
,其中符号-
就是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4
就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版语言,例如00代表英语;第一个分隔符-
之后的三位数字代表出版社,例如670670代表维京出版社;第二个分隔符后的五位数字代表该书在该出版社的编号;最后一位为识别码。
识别码的计算方法如下:
首位数字乘以11加上次位数字乘以22……以此类推,用所得的结果\bmod 11mod11,所得的余数即为识别码,如果余数为1010,则识别码为大写字母XX。例如ISBN号码0-670-82162-4
中的识别码44是这样得到的:对067082162
这99个数字,从左至右,分别乘以1,2,...,91,2,...,9再求和,即0×1+6×2+……+2×9=1580×1+6×2+……+2×9=158,然后取158 \bmod 11158mod11的结果44作为识别码。
你的任务是编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出Right
;如果错误,则输出你认为是正确的ISBN号码。
输入输出格式
输入格式:
一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。
输出格式:
一行,假如输入的ISBN号码的识别码正确,那么输出Right
,否则,按照规定的格式,输出正确的ISBN号码(包括分隔符-
)。
输入输出样例
输入样例#1: 复制
0-670-82162-4
输出样例#1: 复制
Right
输入样例#2: 复制
0-670-82162-0
输出样例#2: 复制
0-670-82162-4
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b,c;char d;
scanf("%d-%d-%d-%c",&a,&b,&c,&d);
int res=0;int aa=a,bb=b,cc=c;
res+=a;int k=4;
while(b){
res+=b%10*(k--);
b/=10;
}
int x=9;
while(c){
res+=c%10*(x--);
c/=10;
}
res%=11;int ccc;
if(d=='X') ccc=10; else ccc=d-'0'; //cout<<ccc<<endl;
if(res==ccc){
cout<<"Right";
}
else if(res==10) printf("%d-%03d-%05d-X",aa,bb,cc);
else
printf("%d-%03d-%05d-%d",aa,bb,cc,res);
return 0;
}
题意挺重要的,类型转化,可能输出ASCI码值,和“X”不符合
题目描述
众所周知,在每一个彗星后都有一只UFO。这些UFO时常来收集地球上的忠诚支持者。不幸的是,他们的飞碟每次出行都只能带上一组支持者。因此,他们要用一种聪明的方案让这些小组提前知道谁会被彗星带走。他们为每个彗星起了一个名字,通过这些名字来决定这个小组是不是被带走的那个特定的小组(你认为是谁给这些彗星取的名字呢?)。关于如何搭配的细节会在下面告诉你;你的任务是写一个程序,通过小组名和彗星名来决定这个小组是否能被那颗彗星后面的UFO带走。
小组名和彗星名都以下列方式转换成一个数字:最终的数字就是名字中所有字母的积,其中AA是11,ZZ是2626。例如,USACOUSACO小组就是21 \times 19 \times 1 \times 3 \times 15=1795521×19×1×3×15=17955。如果小组的数字\bmod 47mod47等于彗星的数字\bmod 47mod47,你就得告诉这个小组需要准备好被带走!(记住“a \bmod bamodb”是aa除以bb的余数;34 \bmod 1034mod10等于44)
写出一个程序,读入彗星名和小组名并算出用上面的方案能否将两个名字搭配起来,如果能搭配,就输出“GO”,否则输出“STAY”。小组名和彗星名均是没有空格或标点的一串大写字母(不超过66个字母)。
输入输出格式
输入格式:
第1行:一个长度为11到66的大写字母串,表示彗星的名字。
第2行:一个长度为11到66的大写字母串,表示队伍的名字。
输出格式:
输入输出样例
输入样例#1: 复制
COMETQ
HVNGAT
输出样例#1: 复制
GO
输入样例#2: 复制
ABSTAR
USACO
输出样例#2: 复制
STAY
说明
题目翻译来自NOCOW。
USACO Training Section 1.1
#include<bits/stdc++.h>
using namespace std;
char a[7];
char b[7];
int main(){
cin>>a;
cin>>b;
int res1=1,res2=1;
int lena=strlen(a);
int lenb=strlen(b);
for(int i=0;i<lena;i++){
res1*=a[i]-'A'+1;
res1%=47;
}
for(int i=0;i<lenb;i++){
res2*=b[i]-'A'+1;
res2%=47;
}
if(res1==res2) cout<<"GO";
else cout<<"STAY";
return 0;
}
新手村的我也做了,因为水平不够。
题目描述
一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数。
现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章
中的某一独立单词在不区分大小写的情况下完全相同(参见样例1 ),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2 )。
输入输出格式
输入格式:
共22行。
第11行为一个字符串,其中只含字母,表示给定单词;
第22行为一个字符串,其中只可能包含字母和空格,表示给定的文章。
输出格式:
一行,如果在文章中找到给定单词则输出两个整数,两个整数之间用一个空格隔开,分别是单词在文章中出现的次数和第一次出现的位置(即在文章中第一次出现时,单词首字母在文章中的位置,位置从00 开始);如果单词在文章中没有出现,则直接输出一个整数-1−1。
输入输出样例
输入样例#1: 复制
To
to be or not to be is a question
输出样例#1: 复制
2 0
输入样例#2: 复制
to
Did the Ottoman Empire lose its power at that time
输出样例#2: 复制
-1
说明
数据范围
1≤1≤单词长度≤10≤10。
1≤1≤文章长度≤1,000,000≤1,000,000。
noip2011普及组第2题
反正要多刷题才对,身为女生,好像竞赛向来都是一个人来着,那么要有自己的计划。一天一定要做大于等于十题,否则太过垃圾了。同时由于意志力薄弱,那么就把玩的时间和写题目的时间各分一半,正常课业都可以忽略了,根本不花时间。
还有洛谷的题目很水,题解也很水。
自动机,有两种情况,或者是字母,或者是空格,前面是字母后面是空格,加1 ,变状态,而反过来不用加1,只要变状态,同时要注意最后一个为字母时要再加1,计算字母的数量,和空格相关,其实很容易想的,不过竟然叫自动机,挺神奇了。
例子:
#include <cstdio>
int main () {
char a[1001];
int state, ans = 0;
gets(a);
if(a[0] == ' ') state = 0;//设置初始值
else state = 1;
for(int i = 1; a[i]; i ++ ) {//要从一开始遍历,因为零已经遍历过了
if(a[i] == ' ') {//是空格
if(state == 1) {//当前状态(前一个)是字母,说明找到一个单词了
ans ++ ;//答案加一
state = 0;//千万别忘了改状态
}
}
else {//是字母
if(state == 0) {//当前状态(前一个)是空格
state = 1;//将状态改为1
}
}
}
if(state == 1)//最后还要判断一下千万不要忘记
ans ++ ;
printf("%d", ans);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
char a[1000010];
char b[20];
void tolow(char *a){
for(int i=0;a[i];i++){
if(isupper(a[i])) a[i]=tolower(a[i]);//有返回值的
}
return ;
}
int main(){
gets(b);//有空格
gets(a);
tolow(a);
tolow(b);
//cout<<a<<endl;
// cout<<b<<endl;
int len=strlen(b);
//cout<<len<<endl;
int state=0;
int space =0;
int letter=-1;
int ans=-1;int an=0;
int i;
for( i=0;a[i];i++){
switch(state){
case 0:
if(a[i]==b[0]) state=1;
else if(a[i]==' ') state=0;
else state=-1;
break;
case -1:
if(a[i]==' ') state=0;
break;
default://并不是只有1这种情况
if(state<len) {
if(a[i]==' ') state=space;
else if(a[i]==b[state]) state++;
else state=-1;
}
else if(state==len){
if(a[i]==' ') {
state=space,an++;
if(ans==-1){
ans=i-len;
}
}
else state=-1;
//后面可以跟着其他字母
}
}
}
if(state==len){
an++;
if(ans==-1){
ans=i-len;
}
}
if(ans==-1){
cout<<-1<<endl;
return 0;
}
cout<<an<<" ";
cout<<ans<<endl;
return 0;
}
之前我都输入错顺序了,细节总是太乱。
题目描述
给一n \times nn×n的字母方阵,内可能蕴含多个“yizhong
”单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 88 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用*
代替,以突出显示单词。例如:
输入:
8 输出:
qyizhong *yizhong
gydthkjy gy******
nwidghji n*i*****
orbzsfgz o**z****
hhgrhwth h***h***
zzzzzozo z****o**
iwdfrgng i*****n*
yyyygggg y******g
输入输出格式
输入格式:
第一行输入一个数nn。(7 \le n \le 1007≤n≤100)。
第二行开始输入n \times nn×n的字母矩阵。
输出格式:
突出显示单词的n \times nn×n矩阵。
输入输出样例
输入样例#1: 复制
7
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
输出样例#1: 复制
*******
*******
*******
*******
*******
*******
*******
输入样例#2: 复制
8
qyizhong
gydthkjy
nwidghji
orbzsfgz
hhgrhwth
zzzzzozo
iwdfrgng
yyyygggg
输出样例#2: 复制
*yizhong
gy******
n*i*****
o**z****
h***h***
z****o**
i*****n*
y******g
#include<bits/stdc++.h>
using namespace std;
char a[110][110];
char cc[7]={'y','i','z','h','o','n','g'};
int vis[110][110];
int viss[110][110];
int n;
void dfs(int i,int j){
vis[i][j]=1;int aa=0,b=0,c=0,d=0,e=0,g=0,f=0,h=0;int ff=1;
int k;int q;
for( k=i+1;k<n;k++){
if(a[k][j]==cc[ff]) vis[k][j]=1,ff++;
else break;
}
if(ff!=7)
for(int kk=i+1;kk<k;kk++){
vis[kk][j]=0;
} else aa=1;
for(int k=i-1;k>=0;k--){
if(a[k][j]==cc[ff++]) vis[k][j]=1,q=k;
else break;
}
if(ff!=7)
for(int k=i-1;k>=q;k--){
if(a[k][j]==cc[ff++]) vis[k][j]=0;
} else b=1;
for(int k=j-1;k>=0;k--){
if(a[i][k]==cc[ff++]) vis[i][k]=1,q=k;
else break;
}
if(ff!=7)
for(int k=j-1;k>=q;k--){
if(a[i][k]==cc[ff++]) vis[i][k]=0;
} else c=1;
for(int k=j+1;k<n;k++){
if(a[i][k]==cc[ff++]) vis[i][k]=1,q=k;
else break;
}
if(ff!=7)
for(int k=j+1;k<=q;k++){
if(a[i][k]==cc[ff++]) vis[i][k]=0;
} else d=1;
for(int k=1;(i+k)<n&&(j+k)<n;k++){
if(a[i+k][j+k]==cc[ff++]) vis[i+k][j+k]=1,q=k;
else break;
}
if(ff!=7)
for(int k=1;k!=q+1;k++){
if(a[i+k][j+k]==cc[ff++]) vis[i+k][j+k]=0;
} else e=1;
for(int k=1;(i+k)<n&&(j-k)>=0;k++){
if(a[i+k][j-k]==cc[ff++]) vis[i+k][j-k]=1,q=k;
else break;
}
if(ff!=7)
for(int k=1;k!=q+1;k++){
if(a[i+k][j-k]==cc[ff++]) vis[i+k][j-k]=0;
} else f=1;
for(int k=1;(i-k)>=0&&(j+k)<n;k++){
if(a[i-k][j+k]==cc[ff++]) vis[i+k][j+k]=1,q=k;
else break;
}
if(ff!=7)
for(int k=1;k!=q+1;k++){
if(a[i-k][j+k]==cc[ff++]) vis[i-k][j+k]=0,q=k;
} else g=1;
for(int k=1;(i+k)<n&&(j-k)>=0;k++){
if(a[i+k][j-k]==cc[ff++]) vis[i+k][j-k]=1,q=k;
else break;
}
if(ff!=7)
for(int k=1;k!=q+1;k++){
if(a[i-k][j-k]==cc[ff++]) vis[i-k][j-k]=0;
} else h=1;
if((aa+b+c+d+e+f+g+h)==0) vis[i][j]=0;
}
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>a[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(a[i][j]=='y'){
//memset(vis,0,sizeof(vis));
dfs(i,j);
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(vis[i][j]) cout<<a[i][j];
else cout<<"*";
}
cout<<endl;
}
return 0;
}
这道题我写的很繁琐,而且死循环了。
#include<bits/stdc++.h>
using namespace std;
char a[110][110];
int vis[110][110];
char cc[]="yizhong";
int dir[][2]={1,1,1,0,0,1,-1,0,0,-1,-1,-1,-1,1,1,-1};
struct node{
int x,y;
}nod[110];
void dfs(int i,int j,node *nod,int k,int cur){
if(cur==7) {
for(int i=0;i<7;i++){
vis[nod[i].x][nod[i].y]=1;
}
}
else {
int dx=i+dir[k][0];
int dy=j+dir[k][1];
if(cur==6||a[dx][dy]==cc[cur+1]){//两个出口
nod[cur].x=i;
nod[cur].y=j;
dfs(dx,dy,nod,k,cur+1);
}
}
}
int main(){
ios::sync_with_stdio(false);
int n;
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>a[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(a[i][j]=='y'){
for(int k=0;k<8;k++){
int dx=i+dir[k][0];
int dy=j+dir[k][1];
if(a[dx][dy]=='i')
dfs(i,j,nod,k,0);
}
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(vis[i][j]) cout<<a[i][j];
else cout<<"*";
}
cout<<endl;
}
return 0;
}
由于两点确定后方向不变,用这个可以简化代码,还有要学会保存路径的方法,还有总是写错的问题需要关注一下了。
题目描述
已知有两个字串A,BA,B及一组字串变换的规则(至多66个规则):
A_1A1 ->B_1B1
A_2A2 -> B_2B2
规则的含义为:在 AA中的子串 A_1A1 可以变换为B_1B1,A_2A2 可以变换为 B_2B2 …。
例如:AA='abcdabcd'BB='xyzxyz'
变换规则为:
‘abcabc’->‘xuxu’‘udud’->‘yy’‘yy’->‘yzyz’
则此时,AA可以经过一系列的变换变为BB,其变换的过程为:
‘abcdabcd’->‘xudxud’->‘xyxy’->‘xyzxyz’
共进行了33次变换,使得AA变换为BB。
输入输出格式
输入格式:
输入格式如下:
AA BB
A_1A1 B_1B1
A_2A2 B_2B2 |-> 变换规则
... ... /
所有字符串长度的上限为2020。
输出格式:
输出至屏幕。格式如下:
若在1010步(包含1010步)以内能将AA变换为BB,则输出最少的变换步数;否则输出"NO ANSWER!"
输入输出样例
输入样例#1: 复制
abcd xyz
abc xu
ud y
y yz
输出样例#1: 复制
3
这道题先放在这儿好了,有点累。
#include<bits/stdc++.h>
using namespace std;
int a[10010];
int jie(int x){
if(a[x]!=x){
return a[x]=jie(a[x]);//路径压缩 ,错误的原因是忘了递归了 ,还有要注意要return
}
else return x;
}
int main(){
int n;
int m;
cin>>n>>m;
for(int i=1;i<=n;i++){
a[i]=i;
}
int cao,x,y;
while(m--)
{
cin>>cao>>x>>y;
switch (cao){
case 1:
x=jie(x);
y=jie(y);//找老大的关系
//if(x>y) swap(x,y);
a[y]=x;
break;
case 2:
if(jie(x)==jie(y)){
cout<<"Y"<<endl;
}
else cout<<"N"<<endl;
break;
}
}
return 0;
}
题目背景
本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779。
题目描述
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
输入输出格式
输入格式:
第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。
接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。
输出格式:
一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)
输入输出样例
输入样例#1: 复制
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
输出样例#1: 复制
0 2 4 3
说明
时空限制:1000ms,128M
数据规模:
对于20%的数据:N<=5,M<=15;
对于40%的数据:N<=100,M<=10000;
对于70%的数据:N<=1000,M<=100000;
对于100%的数据:N<=10000,M<=500000。保证数据随机。
对于真正 100% 的数据,请移步 P4779。请注意,该题与本题数据范围略有不同。
样例说明:
图片1到3和1到4的文字位置调换
果然抄一遍完全还是忘记了,只是知道思想,很难写出来,但是自己写的话,下一次就能很快写出来,如果不是特别复杂的话。
https://blog.csdn.net/acdreamers/article/details/16902023
这个是链式前向星的概念。
#include<bits/stdc++.h>
using namespace std;
const int inf=2147483647;
int vis[10010];int s;int n;
int dis[10010];
struct node{
int next,to,w;
}edge[500010];int num=0;
int head[500010];
void addedge(int l,int r,int w){//链式前向星
edge[++num].next=head[l];
edge[num].to=r;
edge[num].w=w;
head[l]=num;
}
void spfa(){
for(int i=1;i<=n;i++){
dis[i]=inf;
vis[i]=0;
}
queue<int>q;//注意加顶点而非node
q.push(s); dis[s]=0;//原点为0,否则都为无穷大
while(!q.empty())//少了循环
{
int u=q.front();
q.pop() ; vis[u]=0;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(dis[v]>dis[u]+edge[i].w){
dis[v]=dis[u]+edge[i].w;
if(vis[v]==0){
q.push(v);
vis[v]=1;
}
}
}
}
return;
}
int main(){
int m;
cin>>n>>m>>s;int l,r,w;
while(m--){
cin>>l>>r>>w;
addedge(l,r,w);
}
spfa();
for(int i=1;i<=n;i++){
if(i==s) cout<<0<<" ";
else cout<<dis[i]<<" ";
}
return 0;
}
emmm,多写就是了。
题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz
输入输出格式
输入格式:
第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)
接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi
输出格式:
输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz
输入输出样例
输入样例#1: 复制
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出样例#1: 复制
7
说明
时空限制:1000ms,128M
数据规模:
对于20%的数据:N<=5,M<=20
对于40%的数据:N<=50,M<=2500
对于70%的数据:N<=500,M<=10000
对于100%的数据:N<=5000,M<=200000
样例解释:
所以最小生成树的总边权为2+2+3=7
看了果然忘了,还是要写。
pair的应用
pair是将2个数据组合成一个数据,当需要这样的需求时就可以使用pair,如stl中的map就是将key和value放在一起来保存。另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair。 pair的实现是一个结构体,主要的两个成员变量是first second 因为是使用struct不是class,所以可以直接使用pair的成员变量。
make_pair函数
template pair make_pair(T1 a, T2 b) { return pair(a, b); }
很明显,我们可以使用pair的构造函数也可以使用make_pair来生成我们需要的pair。 一般make_pair都使用在需要pair做参数的位置,可以直接调用make_pair生成pair对象很方便,代码也很清晰。 另一个使用的方面就是pair可以接受隐式的类型转换,这样可以获得更高的灵活度。灵活度也带来了一些问题如:
std::pair<int, float>(1, 1.1);
std::make_pair(1, 1.1);
是不同的,第一个就是float,而第2个会自己匹配成double。
make_pair (STL Samples)
转载自
https://blog.csdn.net/weixin_42825576/article/details/81571419
#include<bits/stdc++.h>
using namespace std;
int vis[5005];int head[5005];
int dis[5005];int n;
typedef pair<int,int>pii;
struct node{
int next,to,w;
}edge[400010];int k;int cnt;int sum;
priority_queue<pii,vector<pii>,greater<pii> >q;//优先队列的使用很重要
void addedge(int next,int to ,int w){
edge[++k].to=to;
edge[k].w=w;
edge[k].next=head[next];
head[next]=k;
}
void prim(){
dis[1]=0; q.push(make_pair(0,1)); //vis[1]=1;
while(!q.empty()&&cnt<n){
int d=q.top().first;int e=q.top().second;
if(vis[e]) continue;
cnt++;
sum+=d;//加和
vis[e]=1;
q.pop();
for(int i=head[e];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(dis[v]>edge[i].w){
dis[v]=edge[i].w;
q.push(make_pair(dis[v],v));
}
}
}
}
int main(){
int x,y,w;
int m;
cin>>n>>m;
memset(dis,127,sizeof(dis));//
memset(head,-1,sizeof(head));//初始化
while(m--){
cin>>x>>y>>w;
addedge(x,y,w);
addedge(y,x,w);
}
prim();
if(cnt==n){
cout<<sum<<endl;
}
else cout<<"orz"<<endl;
return 0;
}
题目描述
已知有两个字串A,BA,B及一组字串变换的规则(至多66个规则):
A_1A1 ->B_1B1
A_2A2 -> B_2B2
规则的含义为:在 AA中的子串 A_1A1 可以变换为B_1B1,A_2A2 可以变换为 B_2B2 …。
例如:AA='abcdabcd'BB='xyzxyz'
变换规则为:
‘abcabc’->‘xuxu’‘udud’->‘yy’‘yy’->‘yzyz’
则此时,AA可以经过一系列的变换变为BB,其变换的过程为:
‘abcdabcd’->‘xudxud’->‘xyxy’->‘xyzxyz’
共进行了33次变换,使得AA变换为BB。
输入输出格式
输入格式:
输入格式如下:
AA BB
A_1A1 B_1B1
A_2A2 B_2B2 |-> 变换规则
... ... /
所有字符串长度的上限为2020。
输出格式:
输出至屏幕。格式如下:
若在1010步(包含1010步)以内能将AA变换为BB,则输出最少的变换步数;否则输出"NO ANSWER!"
输入输出样例
输入样例#1: 复制
abcd xyz
abc xu
ud y
y yz
输出样例#1: 复制
3
初步思考,应该要用map对应两个string类型,要对字符串进行更改,长度会变化,显然不能用数组,可能是链表之类的,但是有什么结构和链表很相似呢,不知道,有可能是string ,于是开始考虑,string类型可以加,如何修改,是直接赋值,而且会直接练上去。这道题目是道搜索题,那么规则有限,那么一个个规则轮过去,行的话递归,直到莫状态为止,要注意,不行的话,就回溯。那么所有的情况取最小值。要求极值的话显然是宽度优先搜索了。这就是了,现在才想起来这是BFS。
试验了一下,自己看往往逻辑都混乱,但是写下来就条理分明了。
发现实在太弱了,内心是崩溃的,所以一天要做十题起码,反正一开始比较容易
substr是C++语言函数,主要功能是复制子字符串,要求从指定位置开始,并具有指定的长度。如果没有指定长度_Count或_Count+_Off超出了源字符串的长度,则子字符串将延续到源字符串的结尾。
但是string要对应数字,所以要两个数组,同时map同时判重。
#include<bits/stdc++.h>
using namespace std;
const int maxn=15;
string original[maxn];
string then[maxn];
string a,b;int n;
struct node{
string str;
int step;//要求步骤
};
map<string,int> p;
string trans(const string &str,int i,int j){
string ans="";
if(i+original[j].length()>str.length()){
return ans;
}
for(int k=0;k<original[j].length();k++){
if(str[i+k]!=original[j][k]) {
return ans;
}
}
ans=str.substr(0,i);
ans+=then[j];
ans+=str.substr(i+original[j].length());
return ans;
}
int an=0;
void bfs(){
queue<node> q;
node s;
s.step=0;
s.str=a;
q.push(s);//p[s.str]=1;
while(!q.empty()){
node u = q.front();
q.pop();
if(p.count(u.str)==1) continue;
if(u.str==b) {
an=u.step;
break;
}
p[u.str]=1;
for(int i=0;i<u.str.length();i++){
for(int j=0;j<n;j++){
string temp=trans(u.str,i,j);
if(temp!=""){
node v;
v.step=u.step+1;
v.str=temp;
q.push(v);
}
}
}
}
if(an>10||an==0) cout<<"NO ANSWER!";
else cout<<an;
return;
}
int main(){
cin>>a>>b; n=0;
while(cin>>original[n]>>then[n]){
n++;
}
bfs();
return 0;
}
因为少了一个感叹号,我起码挑食了半个小时,emmm,要死。题目输出格式要注意。
将1,2, \cdots ,91,2,⋯,9共99个数分成33组,分别组成33个三位数,且使这33个三位数构成1:2:31:2:3的比例,试求出所有满足条件的33个三位数。
#include<bits/stdc++.h>
using namespace std;
int a[10];
int main(){
for(int i=1;i<=9;i++){
a[i]=i;
}
do{
int res1=a[1]*100+a[2]*10+a[3];
int res2=a[4]*100+a[5]*10+a[6];
int res3=a[7]*100+a[8]*10+a[9];
if((2*res1==res2)&&(res1*3==res3)) {
cout<<res1<<" "<<res2<<" "<<res3<<endl;
}
}while(next_permutation(a+1,a+10));
return 0;
}
next_permutation 的用法
要会用等比数列,等差数列等