紫薯总览——AC代码+小题解
目录 |
目录
- 第六讲——数据结构基础
- 6.1栈和队列
- 例题6-2 UVa514
- 例题6-3 UVa442
- 6.2链表
- 例题6-4 UVa11988
- 例题6-5 UVa12657
- 6.3树和二叉树
- 例题6-6 UVa679
- 例题6-9 UVa839
- 例题6-10 UVa699
- 6.4图
- 例题6-15 UVa10305
- 例题6-16 UVa10129
- 第七讲——暴力枚举
- 7.1简单枚举
- 例题7-1 UVa725
- 例题7-2 UVa11059
- 例题7-3 UVa10976
- 7.1回溯法
- 例题7-4 UVa524
- 例题7-5 UVa129
- 例题7-6 UVa140
- 例题7-7 UVa1354
- 7.5 路径寻找问题
- 例题7-8 UVa1354
- 例题7-9 UVa1601
- 7.6 迭代加深搜索
- 例题7-9 UVa1601
- 例题7-10 UVa11212
- 第八讲——高效算法设计
- 第九讲——动态规划初步
- 9.1 数字三角形
- 9.1.1数字三角形
- 数字三角形
- 9.2 DAG上的动态规划
- 9.2.1DAG模型
- 矩形嵌套问题
- 硬币问题
- 9.2.4 小结与应用举例
- 例题9.2 巴比伦塔
- 9.3 多阶段决策问题
- 9.3.1 多段图的最短路
- 例题9.4 单项TSP
- 9.3.2 0-1背包问题
- 物品无限的背包问题(完全背包)
- 0-1背包问题
- 例题9.5 劲歌金曲
- 9.4 更多经典模型
- 9.4.1 线性结构上的动态规划
- 9.4.1 最长上升自序列(LIS)
- 连环大跳(跳了很多)
- 第十讲——数据结构基础
- 10.1 数论初步
- 10.1.1 欧几里得算法和唯一分解定理
第六讲——数据结构基础
6.1栈和队列
例题6-2 UVa514
我就是入门半年,还没入门成功的大——
从现在起开始认真刷紫薯(其实是抄紫薯哈哈哈)
每道题的理解都在代码里面。
我是真的弱,如果我有错误,评论里留下你的大名,我一定记在我的报答簿上。
正文 |
让我们一起————入门到入土
话不多说,立马进入正题
不愧是大佬,思路如此清晰
后知后觉——好像应该挂出链接——戳我戳我
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
using namespace std;
#define mid 100007
typedef long long ll;
//紫薯上的题
//就是看出栈顺序能够不能实现
//1。检测此时该入栈的数是否对
//2.检测栈顶的数是否对
//3.两者都不满足就入栈(这样就可以调换顺序)
//tips:为了学好思路,这些都是请参考过紫薯的,不过代码是自己打的
int main(){int a,c[1006],i,t;while(cin>>a&&a!=0){while(1){t=0;cin>>c[1];if(c[1]==0)break; for(i=2;i<=a;i++)cin>>c[i];//这是要求最后的顺序 stack<int>w;int e=1,f=1;while(e<=a)/*全部输出都能够一一对应*/{if(f==c[e])e++,f++;//满足1else if(!w.empty()/*栈里有东西*/&&w.top()==c[e]){w.pop();e++;}else if(f<=a)/*保证还可以入栈,就可以换顺序*/{w.push(f);f++;} else /*上面都不满足就不可能了*/{t=1;break;} }printf("%s\n",t==0?"Yes":"No");}cout<<endl;//注意输出格式
}
return 0;
}
代码抽风还请指证,有啥直接告诉我,我家就住在CSDN
例题6-3 UVa442
构造函数的使用
(**其实我是才学过,但是没用过,也不知道怎么用 **)
废话不多说上代码(题目通道)
图片大小调不了吗?
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
using namespace std;
#define mid 100007
typedef long long ll;
//还是紫薯上的题
//还是用栈实现
/*思路就是字母也入栈,一遇到“)”就进行判断
判断此时顶端的两个乘,如果不能乘,就直接错误,输出error
否则,sum加上,然后把两个相乘后矩形重新放入栈,其实整个过程
没有“()”入栈的情况,嘿嘿
思路清晰,不愧是大佬*/
struct www{int hang;int lie;www(int hang=0,int lie=0):hang(hang),lie(lie){}//这个就是精华,我见都没见过,后面有大作用 //猛男醒悟,这就是我才学的构造函数,居然结构体内也可以用,我还一直以为没有用
}c[30];//记录矩阵
int main(){int a,i,sum,t;char b;cin>>a;while(a--){//朴素的输入 cin>>b;cin>>c[b-'A'].hang>>c[b-'A'].lie; }string s;stack<www>k;//建立栈 while(cin>>s){sum=0,t=0;for(i=0;i<s.size();i++){if(isalpha(s[i]))k.push(c[s[i]-'A']);//是字母就入栈else if(s[i]==')'){//"("没有用,牛逼,大佬 //我看紫薯上的程序也没判断出栈时元素不足两个的情况 www p=k.top();k.pop();www q=k.top();k.pop();//取出最上面两个if(q.lie!=p.hang){t=1;break;}//注意顺序 else{sum+=q.hang*q.lie*p.lie;k.push(www(q.hang,p.lie));/*这就是精华,怎样通过,q.a,p.b再放入栈还*/ }}}if(t==1)cout<<"error"<<endl;else cout<<sum<<endl;
}
return 0;
}
我写代码真是一点都不好看
罪过罪过
慢着,我好像明白了这个构造函数
它其实就是用传进去的两个参数重新构造了一个www变量
字母只是一个表壳,内在就是这个www变量
ohhhhhhhhhhhhhhhhhh
6.2链表
例题6-4 UVa11988
本来使用链表,
可我不想用
其实是我看了好久,都想不通
就屈服于STL的伟大,用list
感觉确实有点慢,链表实现我下次补。
下次一定
血池
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<list>
using namespace std;
#define mid 100007
typedef long long ll;
//还是紫薯上的题
//无奈本人太菜鸡,这个链表怎么也想不通
//就先放过自己,用list
//早知道就用这个了,又浪费傻子几小时
int main(){int i;string s;while(cin>>s){list<char>w;list<char>::iterator it =w.begin();for(i=0;i<s.size();i++){if(s[i]=='['){it=w.begin();//从前面 }else if(s[i]==']'){it=w.end();//从后面 }else{//进入list w.insert(it,s[i]); }}for(it=w.begin();it!=w.end();it++)cout<<*it;cout<<endl;}return 0;
}
对不住了。我看了一下下面一道链表,好像更难
只有先行略过了
菜鸡跳题,毫不犹豫
假装**第四滴血**
例题6-5 UVa12657
6.3树和二叉树
例题6-6 UVa679
大树
周树人
“抓捕周树人和我鲁迅有什么关系”
小球下落
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<list>
using namespace std;
#define mid 100007
typedef long long ll;
/*
//二叉树,简单模拟
int c[1<<20];//1向左移动20位就相当于pow(2,20);
//最大节点个数[(1<<20)-1]
int main(){int a,b,k;while(scanf("%d%d",&a,&b)==2){memset(c,0,sizeof(c));//开关清零int maxmax=(1<<a)-1;//最大结点的标号while(b--){//让b个球挨个下落 k=1;//从1开始落 for(;;){//一开始还以为会超时, c[k]=!c[k];//开变关,关变开k=c[k]?2*k:2*k+1;//节点与两个子节点的关系 if(k>maxmax)break; }}//出界之前的位置 cout<<k/2<<endl;//2*k,2*k+1的1/2都是k } return 0;
}
*/
//上面的会超时,应为他每一个小球都模拟了,浪费了大量时间
//其实我们只用知道小球的编号就可与以知道他的路径
//当在1节点时,编号为偶数,就会走右边,否则走左边
//每个节点都是这个道理
int main(){int a,b,k,p;cin>>p;while(p--){cin>>a>>b;k=1;a--;//只能下降a-1次 while(a--){if(b%2==1){k*=2;//左树比右树多走一个 ,因为每次先走左数 b=(b+1)/2;}else{k=k*2+1;b/=2;}}cout<<k<<endl; }cin>>p;return 0;
}
例题6-9 UVa839
前面跳了两道题,
都是构造树的?没看明白
**菜鸡跳题,毫不犹豫 **
跳的两道题
第一道
第二道
紫薯的思路真的好清晰
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<list>
using namespace std;
#define mid 100007
typedef long long ll;
//紫薯继续
//看题是递归输入,就是个模拟
bool sou(int &k){//才学的引用 ,k值可以进行修改 int e,f,g,h; bool p=true; bool q=true; cin>>e>>f>>g>>h;if(e==0){//左手是个子树 p=sou(e);//记录左边的重量 ,看左边是不是平衡的 }if(g==0){q=sou(g);//记录右边的重量 ,看右边是不是平横的 }k=e+g;return q&&p&&f*e==g*h;//左右和自己都平衡才是平衡
}
int main(){int a,k=0;cin>>a;while(a--){if(sou(k)) cout<<"YES"<<endl;elsecout<<"NO"<<endl;if(a)cout<<endl;}return 0;
}
例题6-10 UVa699
有两个小坑点就是
1.函数记得要有返回值
2.UVA的题对于输出格式好像很严格,行尾有空格都不行
紫薯上就没有没有,导致一直RE
题目传送门
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<list>
using namespace std;
#define mid 100007
typedef long long ll;
//紫薯继续
//多用bool类型
int c[200];
//储存每个水平面的值
void jian(int a){int b;cin>>b;if(b!=-1)c[a]+=b;elsereturn ;//等于-1就是没有路了,直接返回 jian(a-1);//先左 jian(a+1);//后右
}
bool du(){//对第一个节点进行特殊处理int a;cin>>a;if(a==-1)return false;memset(c,0,sizeof(c));//因为多组输入 c[200/2]=a;//第一个节点处于最中间的位置 jian(200/2-1);//先左 jian(200/2+1);//后右 return true;
}
int main(){int t=1;while(du()){int i=0;while(c[i]==0)i++;cout<<"Case "<<t++<<":"<<endl<<c[i++];while(c[i]!=0)cout<<" "<<c[i++];cout<<endl<<endl; }return 0;
}
6.4图
例题6-15 UVa10305
Kahn算法实现
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define mid 1000000007
typedef long long ll;
// 紫薯继续(和平精英千年老二)
//拓扑排序
int du[106],a,b;//记录每个点的入度
vector<int>c[106];//邻接表
int ans[106];//记录答案
void sou(){int k=0,i;queue<int>p;for(i=1;i<=a;i++)//寻找出度为0的点if(du[i]==0)p.push(i);/*放进队列,因为每次开始处理都是从入度为0点开始*/ while(!p.empty()){int xin=p.front();p.pop();ans[++k]=xin;//记录答案/*上面清除了一个入度为0的点,下面要把与之所相连的得点入度给剪掉 */for(i=0;i<c[xin].size();i++){du[c[xin][i]]--;if(du[c[xin][i]]==0){/*如果这时候产生一个新的入度为0 的点 */ p.push(c[xin][i]); }} } for(i=1;i<=a;i++){if(i==1)cout<<ans[i];elsecout<<" "<<ans[i];}cout<<endl;
// if(k!=a)//说明这个环
// return 0;
// else
// return 1;
}
int main(){int e,f;while(scanf("%d%d",&a,&b)==2){if(a==b&&b==0)break;for(int i=1;i<=a;i++){c[i].clear();//临接表清空 }memset(du,0,sizeof(du)); while(b--){cin>>e>>f;du[f]++;//先完成e,才能再完成fc[e].push_back(f);//e->f }sou();}return 0;
}
也可以DFS实现
例题6-16 UVa10129
欧拉回路
本题思路
//用并查集实现
//1.要查询每个点的祖先,有多个祖先的就无法形成通路(判断通路)
//2.有两个点的出度与入度不相等,且相差1。或者每个点出度入度都等
例如 asdsdb bsadjasjda
这个UVa今天交不上去啊
先把代码挂在这里
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define mid 1000000007
typedef long long ll;
// 紫薯继续(和平精英千年老二)
//把单词看成有向边,单词开头末尾看作节点
//用并查集实现
//1.要查询每个点的祖先,有多个祖先的就无法形成通路(判断通路)
//2.有两个点的出度与入度不相等,且相差1
int f[30];//记录祖先节点
int ru[30],chu[30],book[30];
int zu(int a){//寻找祖先节点 if(a!=f[a])return f[a]=zu(f[a]);elsereturn a;
}
void chushihua(){memset(ru,0,sizeof(ru));memset(chu,0,sizeof(chu));memset(book,0,sizeof(book));for(int i=1;i<=26;i++){f[i]=i;}
}
int main(){int a,b,i,ans,r,ch,t;cin>>a;while(a--){r=ch=t=ans=0; chushihua();cin>>b;while(b--){string s;cin>>s;int p=s[0]-'a'+1;int q=s[s.size()-1]-'a'+1;ru[p]++;chu[q]++;int w=zu(p);int z=zu(q);if(w!=z)f[z]=w;//合并 book[p]=book[q]=1;//记录有这个点 }for(i=1;i<=26;i++){if(book[i]){/*看看有几个祖先节点,只有一个才能形成通路*/if(f[i]==i)ans++;//祖先节点+1if(ru[i]!=chu[i]){if(ru[i]-chu[i]==1)r++;else if(chu[i]-ru[i]==1)ch++;//合法的出入度不同就这两种,其他都不正确 elset=1; }//判段if(t||ans>1){break;}}}if(i!=27)cout<<"The door cannot be opened."<<endl;else{if((r==1&&ch==1)||(r==ch&&r==0))cout<<"Ordering is possible."<<endl; elsecout<<"The door cannot be opened."<<endl;}}
}
第七讲——暴力枚举
7.1简单枚举
例题7-1 UVa725
只用枚举前5个数,后五个数会自动形成
最后再判断一下数字是否重复
前排提示:UVA对输出格式有控制,WA死我了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define mid 1000000007
typedef long long ll;
// 紫薯继续(和平精英千年老二)
//暴力也需要优化!
/*直接枚举分子就行,
分母也可以得出,
最后看看有没有重复就行*/
int book[12],a,sum=0,book1[12],t;//两个book,标记两个数
void sou(int b){if(b==6){if(sum%a!=0)return ;//找不到整数被除数int k=sum/a;int q=k;/*记录这个数,因为后面判段数字是否重复时会改变 如果判断没有错误,就可以直接输出*/ //分解k,看是否有元素重合memset(book1,0,sizeof(book1)); for(int i=1;i<=5;i++){if(book[k%10]==1||book1[k%10]==1)//出现过了 return ;book1[k%10]=1; k/=10;}t++;printf("%05d / %05d = %d\n",sum,q,a);return ;}//枚举 for(int i=0;i<=9;i++){int p=sum;if(book[i]==0){sum=sum*10+i;book[i]=1;sou(b+1);sum=p;book[i]=0;}//恢复原来状态}
}
int main(){int w=0;//执行的次数,因为最后输出不带\n while(scanf("%d",&a)&&a){if(w)cout<<endl;w++; memset(book,0,sizeof(book));t=0;sou(1);if(t==0)printf("There are no solutions for %d.\n",a);}return 0;
}
例题7-2 UVa11059
数据比较小,也就是个枚举
枚举起点和终点
终点动态变换,起点固定
两重循环就可以了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define mid 1000000007
typedef long long ll;
// 紫薯继续(和平精英千年老二)
//就是枚举,没别的
ll c[20];
int main(){ll a,i,j,b;ll sum,maxmax,k=0,p;while(scanf("%lld",&a)!=EOF){maxmax=0;for(i=1;i<=a;i++)scanf("%lld",&c[i])A;for(i=1;i<=a;i++){//起点 sum=1;for(j=i;j<=a;j++){//终点移动 sum*=c[j];maxmax=max(sum,maxmax);}}printf("Case #%d: The maximum product is %lld.\n\n", ++k, maxmax);}return 0;
}
例题7-3 UVa10976
数学分析走着
解不等式
x=>2a>=y
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define mid 1000000007
typedef long long ll;
// 紫薯继续(和平精英千年老二)
//数学题?
//解不等式——解出 x=>2a>=y
int c1[10000];
int main(){int a,y,p;while(scanf("%d",&a)!=EOF){p=0;for(y=1;y<=2*a;y++){//y的取值范围//式子变换——a=xy/(x+y) //x=ay/(y-a) if(y-a>0&&(a*y)%(y-a)==0&&(a*y)/(y-a)!=0){c1[++p]=y;//记录答案}}cout<<p<<endl;for(int i=1;i<=p;i++)printf("1/%d = 1/%d + 1/%d\n",a,(a*c1[i])/(c1[i]-a),c1[i]); }return 0;
}
7.1回溯法
例题7-4 UVa524
前排恭喜vj上UVa连炸两天 |
素数环
回溯法
记住最后还要和环首 1 进行判断
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define mid 1000000007
typedef long long ll;
//素数处理
int book[20];//标记数组
int ans[20];//记录答案
int su[50];//记录素数
int a;
void sushu(){for(int i=1;i<=50;i++){for(int j=2;j*j<=i;j++){if(i%j==0){su[i]=1;//素数标记为0break; }}}
}
void sou(int b){if(b==a+1){if(su[ans[b-1]+1]==0){//因为是环状,所以还要与开头 1 判断for(int i=1;i<=a;i++){if(i!=a)//注意输入输出格式cout<<ans[i]<<" ";elsecout<<ans[i];}cout<<endl;return ;}}for(int i=2;i<=a;i++){if(book[i]==0&&su[i+ans[b-1]]==0){book[i]=1;ans[b]=i;sou(b+1);//回溯book[i]=0; }}
}
int main(){int k=0;sushu();while(scanf("%d",&a)!=EOF){if(k!=0)cout<<endl;//注意输入输出格式 printf("Case %d:\n",++k);//第一个数为 1ans[1]=1;sou(2);}
}
例题7-5 UVa129
UVa的输入输出格式是真的难搞
注意子串相等时是怎样比较的
还是回溯法
每次添加一个字母进入字符串,最终顺序就是升序
我有点写不明白,还是自己看吧
紫薯上的一句话:
回溯法中,
应注意不必要的判断,
就像八皇后,每次只用判断新皇和之前的皇是否冲突,而不用判断以前的皇后是否冲突,因为以前已经判断过了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
//这紫薯看的我天天喊牛皮
//回溯的思想
//每次添加一个字母
int w=0;//记录第几个困难串
int a,b,t;
char ans[100];//记录答案
int jian(int c){int mid=c/2;//枚举比较的字串长度int i,j,p;for( i=1;i<=mid;i++){for( j=c+1-2*i,p=c+1-i;p<=c;j++,p++){//两个字串比较是否相等 if(ans[j]!=ans[p])//字串不相等 break; }if(p==c+1)//字串相等return 0; }return 1;
}
void dfs(int c){if(t==1)return ; if(++w==a){/*每次只要进行了dfs函数都会产生一个新的排列所以w++;*/ t=1;//令人烦躁的输出for(int i=1;i<c;i++){cout<<ans[i]; if(i%4==0&&i!=c-1){if(i%64==0)cout<<endl;elsecout<<" ";}}cout<<endl<<c-1<<endl;return ;}for(int i=0;i<b;i++){ans[c]=i+'A';if(jian(c))//如果检查没有重复,就继续下一个dfs(c+1); //只要继续dfs,就是产生了一个排列 //否则就重新选择 }
}
int main(){while(scanf("%d%d",&a,&b)&&b&&a){//平平无奇的输入 w=-1;t=0;dfs(1);}return 0;
}
例题7-6 UVa140
例题7-7 UVa1354
这两个题我愣是没读懂题
7.5 路径寻找问题
例题7-8 UVa1354
烦躁
代码是我抄的,加了点解释
看着比紫薯上好懂
虽然长了点,但有一大段“重复的”
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
/*看紫薯的题解有点抽风,我的木鱼脑袋接受不了
找的其他题解 */
using namespace std;const int MAXN = 200;int a, b, c, d, maxd1, minamount;
bool notvist[MAXN+1][MAXN+1][MAXN+1];struct node {//记录每一个状态int a, b, c, amount;bool operator < (const node& n) const {return amount > n.amount;}//这个是干嘛的??????????????????
};int bfs()
{maxd1 = 0;minamount = 0;//因为是对移动水最少的进行扩展,所以使用优先队列 priority_queue<node> q;//多组输入,标记数组清零 memset(notvist, true, sizeof(notvist));node f, v;f.c = c;f.a = 0;f.b = 0;f.amount=0;//标记初始状态 q.push(f);notvist[f.c][f.a][f.b] = false;//下面进行扩展while(!q.empty()) {f = q.top();//优先队列这里是topq.pop();if(f.a == d || f.b == d || f.c == d)return f.amount;//找到结果,直接退出dfsif(f.a < d && f.a > maxd1) {maxd1 = f.a;minamount = f.amount;}if(f.b < d && f.b > maxd1) {maxd1 = f.b;minamount = f.amount;}if(f.c < d && f.c > maxd1) {maxd1 = f.c;minamount = f.amount;}/*用三个if寻找倒在杯子里的不大于h的最大值顺便记录步数 */// 下面枚举6中操作,大同小异//用v记录操作后的状态 // c --> aif(f.c && a - f.a > 0) {if(f.c > a - f.a) { // c > a的剩余容量v.c = f.c - (a - f.a);v.a = a;v.b = f.b;v.amount = f.amount + (a - f.a);} else { // c <= a的剩余容量v.c = 0;v.a = f.a + f.c;v.b = f.b;v.amount = f.amount + f.c;}if(notvist[v.c][v.a][v.b]) {notvist[v.c][v.a][v.b] = false;q.push(v);}}// c --> bif(f.c && b - f.b > 0) {if(f.c > b - f.b) { // c > b的剩余容量v.c = f.c - (b - f.b);v.a = f.a;v.b = b;v.amount = f.amount + (b - f.b);} else { // c <= b的剩余容量v.c = 0;v.a = f.a;v.b = f.b + f.c;v.amount = f.amount + f.c;}if(notvist[v.c][v.a][v.b]) {notvist[v.c][v.a][v.b] = false;q.push(v);}}// a --> cif(f.a && c - f.c > 0) {if(f.a > c - f.c) { // a > c的剩余容量v.c = c;v.a = f.a - (c - f.c);v.b = f.b;v.amount = f.amount + (c - f.c);} else { // a <= c的剩余容量v.c = f.c + f.a;v.a = 0;v.b = f.b;v.amount = f.amount + f.a;}if(notvist[v.c][v.a][v.b]) {notvist[v.c][v.a][v.b] = false;q.push(v);}}// a --> bif(f.a && b - f.b > 0) {if(f.a > b - f.b) { // a > b的剩余容量v.c = f.c;v.a = f.a - (b - f.b);v.b = b;v.amount = f.amount + (b - f.b);} else { // a <= b的剩余容量v.c = f.c;v.a = 0;v.b = f.b + f.a;v.amount = f.amount + f.a;}if(notvist[v.c][v.a][v.b]) {notvist[v.c][v.a][v.b] = false;q.push(v);}}// b --> cif(f.b && c - f.c > 0) {if(f.b > c - f.c) { // b > c的剩余容量v.c = c;v.a = f.a;v.b = f.b - (c - f.c);v.amount = f.amount + (c - f.c);} else { // b <= c的剩余容量v.c = f.c + f.b;v.a = f.a;v.b = 0;v.amount = f.amount + f.b;}if(notvist[v.c][v.a][v.b]) {notvist[v.c][v.a][v.b] = false;q.push(v);}}// b --> aif(f.b && a - f.a > 0) {if(f.b > a - f.a) { // b > a的剩余容量v.c = f.c;v.a = a;v.b = f.b - (a - f.a);v.amount = f.amount + (a - f.a);} else { // b <= a的剩余容量v.c = f.c;v.a = f.a + f.b;v.b = 0;v.amount = f.amount + f.b;}if(notvist[v.c][v.a][v.b]) {notvist[v.c][v.a][v.b] = false;q.push(v);}}}return -1;
}int main()
{int t;scanf("%d", &t);while(t--) {scanf("%d%d%d%d", &a, &b, &c, &d);int ans = bfs();if(ans < 0) {printf("%d %d\n", minamount, maxd1);} elseprintf("%d %d\n", ans, d);}return 0;
}
例题7-9 UVa1601
双向BFS
不会
7.6 迭代加深搜索
例题7-9 UVa1601
真的佩服看了大量题解看不懂,突然有个大佬的题解明白了
在线跪
牛逼
总结一下
这是那个大佬的题解链接
什么狗屁迭代加深搜索,看的我懵逼了一早上
这个也没涉及什么算法,所以看了还是好懂,但是叫我自己写,肯定写不出来
题目最重要的是每次搜索规定了上下界
还有好多小细节:多用乘法代替除法…
大佬真强
我改了一些细节
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
//真的是难,我要吐了
//真的是半天一道题,还是看的别人的代码
//大佬思路
using namespace std;
const int N=1e5+7;
set <long long> p;
long long t,A,B,n,mxdep;
long long ans[N],w[N];
bool flag;
//inline long long gcd(long long a,long long b)
//{// return b ? gcd(b,a%b) : a;
//}//gcd是为了约分
inline bool pd()
{for(int i=mxdep;i;i--)if(ans[i]!=w[i])return ans[i]&&ans[i]<w[i];return 0;
}//判断答案是否更优
inline void dfs(long long dep,long long a,long long b,long long mi)
{if(dep==mxdep)//还剩最后一个数时 {if(b%a||(b*mi<a)||p.count(b/a)) return;//判断合法性//不合法 /*判断合法性的三个条件 1.可以构成1/n形式2.比mi小3.b/a这个数可以使用*/ //如果合法还要看是否为最优情况w[dep]=b/a;if(pd()) return;//判断答案是否更优memcpy(ans,w,sizeof(w)); flag=1;//更新return;}mi=max(mi,b/a+1);//求出下界for(long long i=mi;i;i++){if( (mxdep-dep+1)*b<=i*a ) return;/*因为每个选择的数其实大小是递减的,如果这个数和以后的数分母都用i的和都比a/b小,那就肯定实现不了后面更大的i就更不用再考虑了*//*用乘法表示的的优势在于不用害怕除法的精度丢失*/if(p.count(i)) continue;//判断合法w[dep]=i;//记录路径long long xa=a*i-b,xb=i*b;//通分
// long long z=gcd(xa,xb);dfs(dep+1,xa,xb,i+1);//i改变因为i是递增的}
}
int main()
{cin>>t;for(long long i=1;i<=t;i++){flag=0; mxdep=1;cin>>A>>B>>n;long long c;p.clear();//细节while(n--) scanf("%lld",&c),p.insert(c);//存储不合法的数while(mxdep++)//分裂成k个数就可以找到答案,从2开始{memset(ans,0,sizeof(ans));dfs(1,A,B,B/A+1);if(flag) break;}//迭代加深printf("Case %lld: %lld/%lld=1/%lld",i,A,B,ans[1]);for(int i=2;i<=mxdep;i++)printf("+1/%lld",ans[i]);printf("\n");}return 0;
}
例题7-10 UVa11212
什么IDA算法了,过
第八讲——高效算法设计
what??????????????
第九讲——动态规划初步
9.1 数字三角形
9.1.1数字三角形
数字三角形
标准的动态规划,容易实现
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
using namespace std;
#define mid 1000000007
int a,ans[102][102],c[102][102];
int sou(int x,int y){if(x==a){//最后一层 return ans[x][y]=c[x][y];}else{if(ans[x][y]!=0)return ans[x][y];else{return ans[x][y]=c[x][y]+max(sou(x+1,y),sou(x+1,y+1));}}
}
int main(){cin>>a;for(int i=1;i<=a;i++){for(int j=1;j<=i;j++){cin>>c[i][j];}}cout<<sou(1,1);
}
9.2 DAG上的动态规划
9.2.1DAG模型
矩形嵌套问题
有向无环图,不清楚DAG的可以博客查一下
感觉和上一道数字三角形差不多
就是
1.记忆化
2.建立有向图
3.保证每个点都有ans值
4.详细的写在代码里了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
using namespace std;
#define mid 1000000007
//有向无环图
int b,ans[1006],xian[1006][1006],c[1006][2];
int dp(int a){int i,maxmax;if(ans[a]>0)return ans[a];//记忆化 maxmax=1;//注意初值设置为1 for(i=1;i<=b;i++){if(xian[a][i])//如果有向边存在 maxmax=max(dp(i)+1,maxmax);}return ans[a]=maxmax;
}
int main(){int a,maxmax,i,j;cin>>a;while(a--){memset(ans,0,sizeof(ans));memset(xian,0,sizeof(xian)); cin>>b;for(i=1;i<=b;i++)cin>>c[i][0]>>c[i][1];//建立有向图for(i=1;i<=b;i++){for(j=1;j<=b;j++){if((c[i][0]>c[j][0]&&c[i][1]>c[j][1])||(c[i][1]>c[j][0]&&c[i][0]>c[j][1])){xian[i][j]=1;//注意是j可以放在i里面 }}}maxmax=-1;//注意下面这样做的理由是//让每一个点肯定都会得到ans for(i=1;i<=b;i++){maxmax=max(maxmax,dp(i));//找出最大的那个ans }cout<<maxmax<<endl;}return 0;
}
硬币问题
这题我都找了好久
不用引用也能错?我吐了
代码是我网上cv的,我的有个样例超时,恶心死我
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
using namespace std;
const int k = 0x3f3f3f3f;//最大最小值
int ans[10006], c[106], book[10006], a, b;//book数组用来记忆化
int da(int x) {if (book[x])return ans[x];book[x] = 1;int &maxmax = ans[x];//不用引用就完蛋maxmax = -k;for (int i = 1; i <= a; i++) {if (x >= c[i]) {maxmax = max(maxmax, da(x - c[i]) + 1);}}return ans[x] = maxmax;
}
int xiao(int x) {if (book[x])return ans[x];book[x] = 1;int &minmin = ans[x];minmin = k;for (int i = 1; i <= a; i++) {if (x >= c[i]) {minmin = min(minmin, xiao(x - c[i]) + 1);}}return minmin;
}
int main() {cin >> a >> b;for (int i = 1; i <= a; i++) {cin >> c[i];}book[0] = 1;ans[0] = 0;cout << xiao(b);memset(book, 0, sizeof(book));book[0] = 1;ans[0] = 0;cout << " " << da(b);
}
9.2.4 小结与应用举例
例题9.2 巴比伦塔
和前面的矩形嵌套大同小异
每个立方体产生三种摆放情况,然后就是标准的记忆化搜索
struct www{int x;int y;int z;
}c[200];//结构体储存每种摆放方式int ans[200],a;int dp(int p){//标准的记忆化搜索int i,maxmax;if(ans[p]){return ans[p];}maxmax=c[p].z;/*记住初始值设置为自己的长度,最短就是没有可以放在上面的,最小值就是自己*/for(i=1;i<=a*3;i++){if((c[i].x<c[p].x&&c[i].y<c[p].y)||(c[i].x<c[p].y&&c[i].y<c[p].x)){maxmax=max(maxmax,dp(i)+c[p].z);}}return ans[p]=maxmax;
}int main(){int i,p,e,f,g,k=0;while(scanf("%d",&a)&&a){p=0;memset(ans,0,sizeof(ans));for(i=1;i<=a;i++){cin>>e>>f>>g;c[++p].x=e,c[p].y=f,c[p].z=g;c[++p].x=f,c[p].y=g,c[p].z=e;c[++p].x=g,c[p].y=e,c[p].z=f;//每个立方体三种摆放方式 }int maxmax=0;for(i=1;i<=a*3;i++){maxmax=max(dp(i),maxmax);}cout<<"Case "<<++k<<": maximum height = "<<maxmax<<endl;}return 0;
}
9.3 多阶段决策问题
9.3.1 多段图的最短路
例题9.4 单项TSP
就是一个DP
注意细节的处理
代码又是一直WA
9.3.2 0-1背包问题
物品无限的背包问题(完全背包)
带权值的dp?就是以前dp的+1变成了+实质的值
int c[103][2], a, b;
int dp[50006];
int sou(int x);
int main() {memset(dp, -1, sizeof(dp));cin >> a >> b;for (int i = 0; i < a; i++) {cin >> c[i][0] >> c[i][1];}cout<<sou(b);return 0;
}
int sou(int x) {if (dp[x] != -1)return dp[x];int maxmax = 0;for (int i = 0; i < a; i++) {if (x >= c[i][0]) {maxmax = max(maxmax, c[i][1] + sou(x - c[i][0]));}}return dp[x] = maxmax;//记忆化
}
0-1背包问题
典型的0-1背包
代码是看了别人的,感觉还是没法独立写出来
int a, b, c[101][2],ans[10006];
int main() {cin >> a >> b;for (int i = 1; i <= a; i++) {cin >> c[i][0] >> c[i][1];}for (int i = 1; i <= a; i++) {for (int j = b; j >=c[i][0]; j--) {//保证可以往包里拿ans[j] = max(ans[j],ans[j-c[i][0]]+c[i][1]);//加上前面的效果}}cout << ans[b];
}
例题9.5 劲歌金曲
可算AC了
也算典型的01背包问题了,时间其实最大是有范围的。
注意最后要留一秒才能唱金曲,详细解释写在代码里了
#include<iostream>
#include<set>
#include<cstring>
#include<algorithm>
#include<string>
#include<stack>
#include<vector>
using namespace std;
//01背包
int k[52];
int ans[10000];//时间是有范围的
int main() {int a, b, c, z = 0;//z是输出时用的cin >> a;while (a--) {memset(ans, -1, sizeof(ans));cin >> b >> c;for (int j = 1; j <= b; j++) {cin >> k[j];}//平凡的输入ans[0] = 0;for (int i = 1; i <= b; i++) {//物品for (int j = c; j >=k[i]; j--) {//时间if (ans[j-k[i]] != -1)//确保j-k[i]在这个时间唱歌有可能实现ans[j] = max(ans[j], ans[j - k[i]] + 1);}}int maxmax = -1, p ;for (int i = 0; i < c; i++) {//等于c的情况特殊处理,因为c时无法唱《金曲》if (ans[i] >=maxmax) {//找最大的ans,并且时间i也要大的,所以有等号maxmax = ans[i];p = i;}}if (maxmax + 1 > ans[c] || (maxmax + 1 == ans[c]&&p+678>c))//条件判断printf("Case %d: %d %d\n", ++z, maxmax + 1, p + 678);elseprintf("Case %d: %d %d\n", ++z, ans[c], c);}return 0;
}
9.4 更多经典模型
9.4.1 线性结构上的动态规划
9.4.1 最长上升自序列(LIS)
只写了最智障的写法,其他的还不懂,后面再来
//最智障的n^2
int dp[1006],c[1006];
int main() {int a;cin >> a;for (int i = 1; i <= a; i++) {cin >> c[i];dp[i] = 1;}for (int i = 1; i <= a; i++) {for (int j = 1; j < i; j++) {if (c[i] > c[j]) {//比前面的数大,才可能形成上升序列dp[i] = max(dp[i], dp[j] + 1);/*表示以i结尾的最长上升序列,所以后面还有个遍历寻找最大*/}}}int ans = 0;for (int i = 0; i <= a; i++) {ans = max(ans, dp[i]);}cout << ans;return 0;
}
连环大跳(跳了很多)
第十讲——数据结构基础
10.1 数论初步
10.1.1 欧几里得算法和唯一分解定理
紫薯总览——AC代码+小题解相关推荐
- 【蓝桥系列】——十三届蓝桥杯PythonB组第五题E题蜂巢(AC代码)
大家好,我是普通小明,初入学习博客,一起加油! 首先,感谢 小蓝刷题 对我的鼓励,我也希望加入学习算法这个大家庭. 第一篇文章,有些不完美,还请多多指教. 目录 (好像我并不会用锚点T-T) 省赛心得 ...
- 紫薯第10章数学 kaungbin专题14数论基础
杂谈 kuangbin14数论Harmonic Number LightOJ - 1234 分段打表 + 欧拉爷爷o(1).(第一次触及了欧拉常熟) 10.1.1 && 10.1.2 ...
- POJ - 2392 朴素多重背包 + 贪心 WA与AC代码细节分析
我们先来看下普通的朴素多重背包(拆成01背包求解) n种物品,背包大小w,每种物品重量 wi,价值 vi,个数 ci dp[j] 表示 大小为 j 的背包含有的最大价值,即 物品重量和 小于等于 j ...
- 例题6-18 UVA12171 Sculpture(90行AC代码)
紫书刷题进行中,题解系列[GitHub|CSDN] 例题6-18 UVA12171 Sculpture(90行AC代码) 题目大意 给定笛卡尔坐标系上的长方体左下角坐标和对应边长,长方体间存在相离,相 ...
- 例题4-6 UVA12412 师兄帮帮忙(156行AC代码)
紫书刷题进行中,题解系列点这里 例题4-6 UVA12412 师兄帮帮忙 思路分析 只需按部就班实现各个功能,虽然繁琐,但无难点.深入思考有助于提高编程能力. 虽实现容易,但新手和老手在效率和代码长度 ...
- 【算法设计与分析】经典常考三十三道例题AC代码
❥小虾目前大三,我校在大一下开设<数据结构>这门课,大二上开了<算法设计与分析>这门课,很庆幸这两门课的上机考试总成绩一门100,一门99,最后总分也都90+.下文会给出机试的 ...
- PAT Basic Level 1027 打印沙漏 解题思路及AC代码
PAT 乙级 1027 打印沙漏 v1.0 1. 题目简述及在线测试位置 2. 基本思路 3. 完整AC代码 1. 题目简述及在线测试位置 1.1 给定N个字符,要求使用尽可能多的字符打印出一个沙漏. ...
- 2019 北邮计算机学院机试 附AC代码以及结果统计
今年计院题目可能比网研难度大一些,没有AK,13人3A,57人2A,98人1A,24人0A 给大家趁热回忆一下题目. 以下题目为回忆版,有些数据细节记不起来了 Problem A 二进制 时间限制 1 ...
- 养生之道——》五红汤、紫薯枸杞银耳汤、山楂红枣红糖水、大枣红糖姜水、红薯汤
版权声明:本文为博主原创文章,无需授权即可转载,甚至无需保留以上版权声明,转载时请务必注明作者. https://blog.csdn.net/weixin_43453386/article/detai ...
最新文章
- SpringCloud 2020版本教程4:使用spring cloud sleuth+zipkin实现链路追踪
- mongodb 对象唯一索引_什么是MongoDB?简介,架构,功能和示例
- Linux 文本界面转到图形界面
- 在c语言中scanf什么时候用,scanf什么时候用??c语言?
- 【C语言简单说】二十一:双重指针基础 (完结)
- 使用标准库函数对象的例子
- 敬伟PS教程:掌握篇B07高级抠图
- Unity_Demo | 中世纪风3D-RPG游戏
- 100流明相当于多少w_lx和瓦数换算(1lx等于多少w)
- 日语 数字 时间 星期 月日 读法总结
- Ubuntu中解压缩命令
- 数列求和-加强版(C语言)
- 做计算机项目的流程图,软件工程实验三(程序流程图和PAD图)
- 后台集成解决方案 avue
- maya(学习笔记)之Arnold渲染器二
- Java中一次对象的自我拯救探究
- java 视频流 读取_Java之视频读取IO流解帧实施方案
- nist是什么软件_NIST推荐什么
- 趣味测试小程序源码带流量主广告位开源小程序
- React 大数据可视化(大屏展示)解决方案
热门文章
- 如何用python制作成绩单生成器【安城安教具】-【其它】-【成绩单生成器】
- DBCO-amine Cas:1255942-06-3,DBCO-NH2,二苯基环辛炔-氨基可衍生DBCO-PEG-NH2
- 前向传播和反向传播(举例说明)
- JArray的使用以及动态获取对象属性值
- 手机计算机隐藏功能怎么关闭,手机计算机自带的隐藏功能,我也是现在才知道,功能比你想得多...
- 城市生命线安全风险综合监测预警解决方案
- OTP概念及实现原理简析 安当加密
- 从《学术津梁》看草书创作轨程
- MySQL查每周、每月、每年、每天数据
- php的封装construct构造方法,__construct() 构造函数