实验名称 |
实验六 窗口 |
实验内容 | |
在某图形操作系统中,有 N 个窗口,每个窗口都是一个两边与坐标轴分别平行的矩形区域。窗口的边界上的点也属于该窗口。窗口之间有层次的区别,在多于一个窗口重叠的区域里,只会显示位于顶层的窗口里的内容。 | |
实验要求 | |
输入格式 输入的第一行有两个正整数,即 N 和 M。(1 ≤ N ≤ 10,1 ≤ M ≤ 10) 输出格式 输出包括 M 行,每一行表示一次鼠标点击的结果。如果该次鼠标点击选择了一个窗口,则输出这个窗口的编号(窗口按照输入中的顺序从 1 编号到 N);如果没有,则输出"IGNORED"(不含双引号)。 | |
主要仪器设备 |
台式或笔记本电脑 |
实验记录(写出实验内容中的程序代码和运行结果)(可分栏或加页) | |
#include<iostream> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int maxn=1000; struct Node { int x1,y1; int x2,y2; int in; }N[10];
int main(void) { int n,m; int i,j,k; int x,y; while(cin>>n>>m) { for(i=0;i<n;i++) { cin>>N[i].x1>>N[i].y1>>N[i].x2>>N[i].y2; N[i].in=i+1; } for(i=0;i<m;i++) { bool flag=true; cin >> x >> y; for(j=n-1; j>=0; j--) { if(x>=N[j].x1 && x<=N[j].x2 && y>=N[j].y1 && y<=N[j].y2) { cout << N[j].in << endl; Node temp = N[j];//位置变化 for(k=j+1; k<n; k++) { N[k-1] = N[k]; } N[n-1] = temp; flag = false; break; } } if(flag) cout << "IGNORED" << endl; } } return 0; } | |
遇到的问题和解决方法 | |
位置变换这儿想了好久才知道可以用数组存储解决 | |
心得体会 | |
这道题算简单的了,不过细节处对我来说还是有点难想到。 |
实验名称 |
实验七 集合竞价 |
实验内容 | |
某股票交易所请你编写一个程序,根据开盘前客户提交的订单来确定某特定股票的开盘价和开盘成交量。 | |
实验要求 | |
输入格式 输入数据有任意多行,每一行是一条记录。保证输入合法。股数为不超过108的正整数,出价为精确到恰好小数点后两位的正实数,且不超过10000.00。 输出格式 你需要输出一行,包含两个数,以一个空格分隔。第一个数是开盘价,第二个是此开盘价下的成交量。开盘价需要精确到小数点后恰好两位。 | |
主要仪器设备 |
台式或笔记本电脑 |
实验记录(写出实验内容中的程序代码和运行结果)(可分栏或加页) | |
#include<iostream> #include<cstdio> #include<algorithm> #include<iomanip> #include<set> using namespace std;
typedef long long ll; const int MAX = 5007; struct _Node{ string m; //buy, sell, cancel double p; //出价 int s; //股数 bool e; //标记第i位的数字是否取消,为true则取消 }r[MAX]; //直接将数组开到最大 set<double> st;
int main(){ int i=0, j=0; while(cin >> r[j].m){ if(r[j].m[0] == 'c'){ cin >> r[j].s; r[r[j].s-1].e = true; j++; continue; } cin >> r[j].p >> r[j].s; j++; } for(i=0; i<j; i++) if(r[i].m[0] != 'c' && r[i].e==false) st.insert(r[i].p); ll m_sum = 0; double p = 0; //循环 求出p0的最佳位置 for(set<double>::iterator it=st.begin(); it!=st.end(); ++it){ double p0 = *it; ll sumb=0, sums=0, sum=0; //买的总和, 卖的总和,sum取二者最小
for(i=0; i<j; i++) if(r[i].m[0] == 's' && !r[i].e && r[i].p<=p0) sums += r[i].s;
for(i=0; i<j; ++i) if(r[i].m[0] == 'b' && !r[i].e && r[i].p>=p0) sumb += r[i].s;
sum = min(sums, sumb); if(sum >= m_sum){ m_sum = sum; p = p0; } } cout << fixed << setprecision(2) << p << " " << m_sum << endl;
return 0; } | |
遇到的问题和解决方法 | |
想到用结构体了,但是不是知道该怎么确定最后出价还有就是cancel要如何取消,看了看题解发现出价就在卖家和买家给的假钱上选,取消也要放在结构体里标记。还有就是没想到排序。 | |
心得体会 | |
Set还是蛮好的:自动从小到大排序。用优先队列也可以做,只不过这只需要price |
实验名称 |
实验八 游戏 |
实验内容 | |
小明在玩一个电脑游戏,游戏在一个n×m的方格图上进行,小明控制的角色开始的时候站在第一行第一列,目标是前往第n行第m列。 | |
实验要求 | |
输入格式 输入的第一行包含三个整数n, m, t,用一个空格分隔,表示方格图的行数n、列数m,以及方格图中有危险的方格数量。 输出格式 输出一个整数,表示小明最快经过几个时间单位可以过关。输入数据保证小明一定可以过关。 | |
主要仪器设备 |
台式或笔记本电脑 |
实验记录(写出实验内容中的程序代码和运行结果)(可分栏或加页) | |
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; const int N=100+10; const int M=100+10; const int T=300+10; //最大可能的时间不可能大于所有的格子数 const int dx[]={0,0,-1,1};//上下走 const int dy[]={-1,1,0,0};//左右走 struct Node { int x,y,t;//x, y 为所在位置,t为时间 Node(int a,int b,int c)//也可以不写,那么入队则需要q.push((Node)u) { x=a; y=b; t=c; } }; queue<Node> q; bool d[N][M][T]; int l[N][M], r[N][M]; int n, m, k; int bfs() { q.push(Node(1, 1, 0)); d[1][1][0] = true; while(!q.empty()) { Node u = q.front(); int ux=u.x, uy=u.y, ut=u.t; q.pop(); for(int i=0; i<4; i++) { int nx = ux+dx[i], ny = uy+dy[i], nt = u.t+1;
if(nx>n || nx<=0 || ny>m || ny<=0 || d[nx][ny][nt]) continue;//是否越界或搜过 if(nt<=r[nx][ny] && nt>=l[nx][ny]) continue;//在此时间内不能走动 if(nx==n && ny==m) return nt;//到达终点,结束
q.push(Node(nx, ny, nt)); d[nx][ny][nt] = true; } } return 0; } int main() { int a, b; scanf("%d%d%d", &n, &m, &k);
memset(d, false, sizeof(d)); memset(l, -1, sizeof(l)); memset(r, -1, sizeof(r)); for(int i=0; i<k; i++) { scanf("%d%d", &a, &b);//位置 scanf("%d%d", &l[a][b], &r[a][b]);//在l-r时间段内不能走动 } printf("%d\n", bfs());
return 0; } | |
遇到的问题和解决方法 | |
刚看这个题的时候不知道该怎么让人不在禁止的时间继续搜索,看了看网上的题解,发现他们用的三维数组,就借鉴别人的写了下。 | |
心得体会 | |
Bfs+queue 这个和模板差不多,稍稍修改下就可以了,所发现的困难就是禁止时间了;该题用三维数组来看是不是可以走还是蛮好玩的。 |
实验名称 |
实验九 高速公路 |
实验内容 | |
某国有n个城市,为了使得城市间的交通更便利,该国国王打算在城市之间修一些高速公路,由于经费限制,国王打算第一阶段先在部分城市之间修一些单向的高速公路。 | |
实验要求 | |
输入格式 输入的第一行包含两个整数n, m,分别表示城市和单向高速公路的数量。 输出格式 输出一行,包含一个整数,表示便利城市对的数量。 样例输入 5 5 样例输出 3 | |
主要仪器设备 |
台式或笔记本电脑 |
实验记录(写出实验内容中的程序代码和运行结果)(可分栏或加页) | |
#include<iostream> using namespace std; #include<cstring> #include<algorithm> int n,m; int head[10010],stack[10010],DFN[10010],Low[10010]; int Belong[10010],instack[10010],cnt,top,f,scnt; struct Node { int e,next; }edge[100010]; void add(int s,int e) { edge[f].e=e; edge[f].next=head[s]; head[s]=f++;//链式前向星 } void tarjan(int s) { int t,k,i; DFN[s]=Low[s]=++cnt; stack[top++]=s;//模拟栈,也可直接用栈push instack[s]=1;//用来判断是否在栈里 for(i=head[s];i!=-1;i=edge[i].next) { k=edge[i].e;// if(!DFN[k]) { tarjan(k); Low[s]=min(Low[k],Low[s]); } else if(instack[k]) { Low[s]=min(Low[s],DFN[k]); } } if(Low[s]==DFN[s])//根结点 { scnt++; do { t=stack[--top]; Belong[t]=scnt;//所属第几个强联通分量 instack[t]=0; } while(s!=t); } } int main() { int i,j,a,b,v[10010]; cin>>n>>m; f=1; memset(head,-1,sizeof(head)); memset(v,0,sizeof(v)); memset(edge, 0, sizeof(edge)); for(i=0;i<m;i++) { cin>>a>>b; add(a,b);//也可选择用向量数组存储 }
memset(DFN,0,sizeof(DFN));
for(i=1;i<=n;i++) { if(!DFN[i]) tarjan(i); } for(i=1;i<=n;i++) v[Belong[i]]++;//每个城市所在的强联通分量连接了多少条边 long long sum=0; for(i=0;i<=n;i++) { if(v[i]>1) sum=sum+v[i]*(v[i]-1)/2;//C(n, 2) } cout<<sum<<endl; return 0; } | |
遇到的问题和解决方法 | |
必须清空该结构体或向量数组,也必须清空,否则当测试数据递减时 WA。 公式可简化为C(2,n)=n(n−1)/2。用dfs会运行超时 | |
心得体会 | |
学了一点tarjan,也了解了邻接表,就是运用起来还有点困难。这道题相当于强联通的模板题了,直接套进去就好了。 |