算法-蓝桥杯习题(4-1)
/* 算法提高 两条直线 问题描述 给定平面上n个点。 求两条直线,这两条直线互相垂直,而且它们与x轴的夹角为45度,并且n个点中离这两条直线的曼哈顿距离的最大值最小。 两点之间的曼哈顿距离定义为横坐标的差的绝对值与纵坐标的差的绝对值之和,一个点到两条直线的曼哈顿距离是指该点到两条直线上的所有点的曼哈顿距离中的最小值。 输入格式 第一行包含一个数n。 接下来n行,每行包含两个整数,表示n个点的坐标(横纵坐标的绝对值小于109)。 输出格式 输出一个值,表示最小的最大曼哈顿距离的值,保留一位小数。 样例输入 4 1 0 0 1 2 1 1 2 样例输出 1.0 数据规模与约定 对于30%的数据,n<=100。 对于另外30%的数据,坐标范的绝对值小于100。 对于100%的数据,n<=10的5次方。 */ #include#include #include #include using namespace std; const int N=100000; struct P{int x,y;}; bool cmp(P a,P b){ if(a.x==b.x)return a.y<b.y; return a.x<b.x; } P d[N+5]; struct F{int max,min;}; F fl[N+5],fr[N+5]; inline double Max(double a,double b){return a>b?a:b;} inline double Min(double a,double b){return a>b?b:a;} bool check(double m,int n){ m*=2; int i,j=0; for(i=0;i ){ while(j ; double MAX=-1e10; double MIN=1e10; if(j!=n){ MAX=Max(MAX,fr[j].max); MIN=Min(MIN,fr[j].min); } if(i-1>=0){ MAX=Max(MAX,fl[i-1].max); MIN=Min(MIN,fl[i-1].min); } // cout< if(MAX-MIN<=m)return true; } return false; } void init(int n){ int i; fl[0].min=fl[0].max=d[0].y; for(i=1;i ){ fl[i].max =Max(fl[i-1].max,d[i].y); fl[i].min=Min(fl[i-1].min,d[i].y); } fr[n-1].min=fr[n-1].max=d[n-1].y; for(i=n-2;i>=0;i--){ fr[i].max=Max(fr[i+1].max,d[i].y); fr[i].min=Min(fr[i+1].min,d[i].y); } } int main(){ int i,n; cin>>n; for(i=0;i){ int x,y; scanf("%d%d",&x,&y); d[i].x=x+y; d[i].y=x-y; } sort(d,d+n,cmp); init(n); double l=0.0; double r=1000000000; while(r-l>=0.01){ double m=(l+r)/2; // cout< if(check(m,n))r=m; else l=m; } printf("%.1f\n",r); return 0; }
/* 算法提高 矩阵翻转 问题描述 Ciel有一个N*N的矩阵,每个格子里都有一个整数。 N是一个奇数,设X = (N+1)/2。Ciel每次都可以做这样的一次操作:他从矩阵选出一个X*X的子矩阵,并将这个子矩阵中的所有整数都乘以-1。 现在问你经过一些操作之后,矩阵中所有数的和最大可以为多少。 输入格式 第一行为一个正整数N。 接下来N行每行有N个整数,表示初始矩阵中的数字。每个数的绝对值不超过1000。 输出格式 输出一个整数,表示操作后矩阵中所有数之和的最大值。 样例输入 3 -1 -1 1 -1 1 -1 1 -1 -1 样例输出 9 数据规模与约定 1 <= N <= 33,且N为奇数。 */ #includeint x[33][33],ans,N; void fun1(int n) { int i,j,lin=0,aa,bb; for(j=0;j ) lin+=x[n-1][j]; for(i=0;i 1;i++) { aa=-1000000000; bb=x[i][n-1]+x[i+n][n-1]; for(j=0;j 1;j++) bb+=abs(x[i][j]+x[i+n][j]+x[i][j+n]+x[i+n][j+n]); aa=aa>bb?aa:bb; bb=-x[i][n-1]-x[i+n][n-1]; for(j=0;j 1;j++) bb+=abs(-x[i][j]-x[i+n][j]+x[i][j+n]+x[i+n][j+n]); aa=aa>bb?aa:bb; lin+=aa; } ans=ans>lin?ans:lin; } void fun(int n) { int i,j,k; for(k=0;k<(1< 1);k++) { for(i=0;i 1;i++) if((k&(1<0) for(j=0;j ) { x[j][i]*=-1; x[j][i+n]*=-1; } fun1(n); for(i=0;i 1;i++) if((k&(1<0) for(j=0;j ) { x[j][i]*=-1; x[j][i+n]*=-1; } } } int main(void) { int i,j,k; scanf("%d",&N); for(i=0;i ) for(j=0;j ) scanf("%d",&x[i][j]); k=(N+1)/2; ans=-1000000000; fun(k); for(i=0;i ) for(j=0;j ) x[i][j]=-x[i][j]; fun(k); printf("%d\n",ans); return 0; }
/* 算法提高 金属采集 问题描述 人类在火星上发现了一种新的金属!这些金属分布在一些奇怪的地方,不妨叫它节点好了。一些节点之间有道路相连,所有的节点和道路形成了一棵树。一共有 n 个节点,这些节点被编号为 1~n 。人类将 k 个机器人送上了火星,目的是采集这些金属。这些机器人都被送到了一个指定的着落点, S 号节点。每个机器人在着落之后,必须沿着道路行走。当机器人到达一个节点时,它会采集这个节点蕴藏的所有金属矿。当机器人完成自己的任务之后,可以从任意一个节点返回地球。当然,回到地球的机器人就无法再到火星去了。我们已经提前测量出了每条道路的信息,包括它的两个端点 x 和 y,以及通过这条道路需要花费的能量 w 。我们想花费尽量少的能量采集所有节点的金属,这个任务就交给你了。 输入格式 第一行包含三个整数 n, S 和 k ,分别代表节点个数、着落点编号,和机器人个数。 接下来一共 n-1 行,每行描述一条道路。一行含有三个整数 x, y 和 w ,代表在 x 号节点和 y 号节点之间有一条道路,通过需要花费 w 个单位的能量。所有道路都可以双向通行。 输出格式 输出一个整数,代表采集所有节点的金属所需要的最少能量。 样例输入 6 1 3 1 2 1 2 3 1 2 4 1000 2 5 1000 1 6 1000 样例输出 3004 样例说明 所有机器人在 1 号节点着陆。 第一个机器人的行走路径为 1->6 ,在 6 号节点返回地球,花费能量为1000。 第二个机器人的行走路径为 1->2->3->2->4 ,在 4 号节点返回地球,花费能量为1003。 第一个机器人的行走路径为 1->2->5 ,在 5 号节点返回地球,花费能量为1001。 数据规模与约定 本题有10个测试点。 对于测试点 1~2 , n <= 10 , k <= 5 。 对于测试点 3 , n <= 100000 , k = 1 。 对于测试点 4 , n <= 1000 , k = 2 。 对于测试点 5~6 , n <= 1000 , k <= 10 。 对于测试点 7~10 , n <= 100000 , k <= 10 。 道路的能量 w 均为不超过 1000 的正整数。 */ #include#include using namespace std; const int MAXN=100000+10,oo=100000000,MAXK=10+1; typedef long long LL; int N,S,K,fa[MAXN]; int g[MAXN],num[MAXN*2],next[MAXN*2],cost[MAXN*2],tot=1; LL f[MAXN][MAXK],sum; inline void read(int &x) { char ch; while (ch=getchar(),ch>'9' || ch<'0') ; x=ch-48; while (ch=getchar(),ch<='9' && ch>='0') x=x*10+ch-48; } inline void addedge(int a,int b,int c) { ++tot; num[tot]=b; next[tot]=g[a]; g[a]=tot; cost[tot]=c; } void dfs(int x) { for (int i=g[x];i;i=next[i]) if (num[i]!=fa[x]) { fa[num[i]]=x; dfs(num[i]); for (int a=K;a;--a) for (int b=1;b<=a;++b) f[x][a]=max(f[x][a],f[x][a-b]+f[num[i]][b]+(LL)(-b+2)*cost[i]); } } int main() { read(N); read(S); read(K); for (int i=1;i i) { int x,y,z; read(x); read(y); read(z); sum+=z; addedge(x,y,z); addedge(y,x,z); } sum=sum+sum; dfs(S); LL ans=oo; ans=ans*ans; for (int i=0;i<=K;++i) ans=min(ans,sum-f[S][i]); cout << ans << endl; return 0; }
/* 算法提高 道路和航路 问题描述 农夫约翰正在针对一个新区域的牛奶配送合同进行研究。他打算分发牛奶到T个城镇(标号为1..T),这些城镇通过R条标号为(1..R)的道路和P条标号为(1..P)的航路相连。 每一条公路i或者航路i表示成连接城镇Ai(1<=A_i<=T)和Bi(1<=Bi<=T)代价为Ci。每一条公路,Ci的范围为0<=Ci<=10,000;由于奇怪的运营策略,每一条航路的Ci可能为负的,也就是-10,000<=Ci<=10,000。 每一条公路都是双向的,正向和反向的花费是一样的,都是非负的。 每一条航路都根据输入的Ai和Bi进行从Ai->Bi的单向通行。实际上,如果现在有一条航路是从Ai到Bi的话,那么意味着肯定没有通行方案从Bi回到Ai。 农夫约翰想把他那优良的牛奶从配送中心送到各个城镇,当然希望代价越小越好,你可以帮助他嘛?配送中心位于城镇S中(1<=S<=T)。 输入格式 输入的第一行包含四个用空格隔开的整数T,R,P,S。 接下来R行,描述公路信息,每行包含三个整数,分别表示Ai,Bi和Ci。 接下来P行,描述航路信息,每行包含三个整数,分别表示Ai,Bi和Ci。 输出格式 输出T行,分别表示从城镇S到每个城市的最小花费,如果到不了的话输出NO PATH。 样例输入 6 3 3 4 1 2 5 3 4 5 5 6 10 3 5 -100 4 6 -100 1 3 -10 样例输出 NO PATH NO PATH 5 0 -95 -100 数据规模与约定 对于20%的数据,T<=100,R<=500,P<=500; 对于30%的数据,R<=1000,R<=10000,P<=3000; 对于100%的数据,1<=T<=25000,1<=R<=50000,1<=P<=50000。 */ #include#include #include #include #include #include #include #define clr(a,b) memset(a, b, sizeof(a)) using namespace std; const int N = 25050; const int E = 150500; //邻接表 int h[N], v[E], w[E], nxt[E], el; void initEdge() { clr(h, -1); el = 0; } void addEdge(int x, int y, int z) { v[el] = y; w[el] = z; nxt[el] = h[x]; h[x] = el++; } //belong[i] 表示节点 i 所在的强连通分量; //cnt 表示强连通分量的个数; int dfn[N], sta[N], low[N], belong[N]; int top, cnt, ind, n; bool vis[N]; void TarjanSolve(int u) { dfn[u] = low[u] = ++ind; vis[u] = true; sta[++top] = u; for(int p=h[u]; ~p; p=nxt[p]) { int i = v[p]; if(!dfn[i]) { TarjanSolve(i); if(low[i] < low[u]) low[u] = low[i]; } else if(vis[i] && dfn[i] < low[u]) low[u] = dfn[i]; } if(dfn[u] == low[u]) { ++cnt; while(1) { int i = sta[top--]; vis[i] = false; belong[i] = cnt; if(i == u) break; } } } void Tarjan() {//注意节点是从几开始存的 clr(dfn, 0); clr(vis, 0); top = cnt = ind = 0; for(int i=1; i<=n; i++)//这里节点从1开始存,若从0开始存要改这里 if(!dfn[i]) TarjanSolve(i); } struct EDGE { int u, v, w; bool flag; EDGE(){} EDGE(int x, int y, int z, bool f):u(x), v(y), w(z), flag(f){} } edge[E]; int edgel; bool visitable[N]; void dfs(int x) { visitable[x] = true; for(int i=h[x]; ~i; i=nxt[i]) { if(!visitable[v[i]]) { dfs(v[i]); } } } int indegree[N]; //链表 int lh[N], lel, lv[E], lnxt[E]; void initLink() { clr(lh, -1); lel = 0; } void addLink(int x, int y) { lv[lel] = y; lnxt[lel] = lh[x]; lh[x] = lel++; } int dis[N]; bool tag[N]; int main() { int r, p, s; while(~scanf("%d%d%d%d", &n, &r, &p, &s)) { clr(visitable, 0); initEdge(); edgel = 0; int x, y, z; for(int i=0; i ) { scanf("%d%d%d", &x, &y, &z); addEdge(x, y, z); addEdge(y, x, z); edge[edgel++] = EDGE(x, y, z, false); } for(int i=0; i ) { scanf("%d%d%d", &x, &y, &z); addEdge(x, y, z); edge[edgel++] = EDGE(x, y, z, true); } Tarjan(); dfs(s); initEdge(); initLink(); clr(indegree, 0); for(int i=0; i
) { if(visitable[edge[i].u] && visitable[edge[i].v]) { addEdge(edge[i].u, edge[i].v, edge[i].w); if(edge[i].flag) { ++ indegree[belong[edge[i].v]]; addLink(belong[edge[i].v], edge[i].v); } else { addEdge(edge[i].v, edge[i].u, edge[i].w); } } } stack<int> zeroDegree; priority_queue int,int> > que; clr(vis, false); clr(tag, false); clr(dis, 0x3f); dis[s] = 0; que.push(make_pair(0, s)); while(!que.empty() || !zeroDegree.empty()) { if(que.empty()) { int x = zeroDegree.top(); zeroDegree.pop(); for(int i=lh[x]; ~i; i=lnxt[i]) { int y = lv[i]; if(!vis[y]) { vis[y] = true; que.push(make_pair(-dis[y], y)); } } } else { int x = que.top().second; que.pop(); if(tag[x]) continue; tag[x] = true; for(int i=h[x]; ~i; i=nxt[i]) { int y = v[i]; if(!tag[y] && dis[y] > dis[x] + w[i]) { dis[y] = dis[x] + w[i]; if(belong[x] == belong[y]) { que.push(make_pair(-dis[y], y)); } } if(belong[x] != belong[y]) { -- indegree[belong[y]]; if(indegree[belong[y]] == 0) { zeroDegree.push(belong[y]); } } } } } for(int i=1; i<=n; i++) { if(visitable[i]) { printf("%d\n", dis[i]); } else { puts("NO PATH"); } } } return 0; }
/* 算法提高 道路和航路 问题描述 农夫约翰正在针对一个新区域的牛奶配送合同进行研究。他打算分发牛奶到T个城镇(标号为1..T),这些城镇通过R条标号为(1..R)的道路和P条标号为(1..P)的航路相连。 每一条公路i或者航路i表示成连接城镇Ai(1<=A_i<=T)和Bi(1<=Bi<=T)代价为Ci。每一条公路,Ci的范围为0<=Ci<=10,000;由于奇怪的运营策略,每一条航路的Ci可能为负的,也就是-10,000<=Ci<=10,000。 每一条公路都是双向的,正向和反向的花费是一样的,都是非负的。 每一条航路都根据输入的Ai和Bi进行从Ai->Bi的单向通行。实际上,如果现在有一条航路是从Ai到Bi的话,那么意味着肯定没有通行方案从Bi回到Ai。 农夫约翰想把他那优良的牛奶从配送中心送到各个城镇,当然希望代价越小越好,你可以帮助他嘛?配送中心位于城镇S中(1<=S<=T)。 输入格式 输入的第一行包含四个用空格隔开的整数T,R,P,S。 接下来R行,描述公路信息,每行包含三个整数,分别表示Ai,Bi和Ci。 接下来P行,描述航路信息,每行包含三个整数,分别表示Ai,Bi和Ci。 输出格式 输出T行,分别表示从城镇S到每个城市的最小花费,如果到不了的话输出NO PATH。 样例输入 6 3 3 4 1 2 5 3 4 5 5 6 10 3 5 -100 4 6 -100 1 3 -10 样例输出 NO PATH NO PATH 5 0 -95 -100 数据规模与约定 对于20%的数据,T<=100,R<=500,P<=500; 对于30%的数据,R<=1000,R<=10000,P<=3000; 对于100%的数据,1<=T<=25000,1<=R<=50000,1<=P<=50000。 */ #include#include #include #include #include #include #include #define clr(a,b) memset(a, b, sizeof(a)) using namespace std; const int N = 25050; const int E = 150500; //邻接表 int h[N], v[E], w[E], nxt[E], el; void initEdge() { clr(h, -1); el = 0; } void addEdge(int x, int y, int z) { v[el] = y; w[el] = z; nxt[el] = h[x]; h[x] = el++; } //belong[i] 表示节点 i 所在的强连通分量; //cnt 表示强连通分量的个数; int dfn[N], sta[N], low[N], belong[N]; int top, cnt, ind, n; bool vis[N]; void TarjanSolve(int u) { dfn[u] = low[u] = ++ind; vis[u] = true; sta[++top] = u; for(int p=h[u]; ~p; p=nxt[p]) { int i = v[p]; if(!dfn[i]) { TarjanSolve(i); if(low[i] < low[u]) low[u] = low[i]; } else if(vis[i] && dfn[i] < low[u]) low[u] = dfn[i]; } if(dfn[u] == low[u]) { ++cnt; while(1) { int i = sta[top--]; vis[i] = false; belong[i] = cnt; if(i == u) break; } } } void Tarjan() {//注意节点是从几开始存的 clr(dfn, 0); clr(vis, 0); top = cnt = ind = 0; for(int i=1; i<=n; i++)//这里节点从1开始存,若从0开始存要改这里 if(!dfn[i]) TarjanSolve(i); } struct EDGE { int u, v, w; bool flag; EDGE(){} EDGE(int x, int y, int z, bool f):u(x), v(y), w(z), flag(f){} } edge[E]; int edgel; bool visitable[N]; void dfs(int x) { visitable[x] = true; for(int i=h[x]; ~i; i=nxt[i]) { if(!visitable[v[i]]) { dfs(v[i]); } } } int indegree[N]; //链表 int lh[N], lel, lv[E], lnxt[E]; void initLink() { clr(lh, -1); lel = 0; } void addLink(int x, int y) { lv[lel] = y; lnxt[lel] = lh[x]; lh[x] = lel++; } int dis[N]; bool tag[N]; int main() { int r, p, s; while(~scanf("%d%d%d%d", &n, &r, &p, &s)) { clr(visitable, 0); initEdge(); edgel = 0; int x, y, z; for(int i=0; i ) { scanf("%d%d%d", &x, &y, &z); addEdge(x, y, z); addEdge(y, x, z); edge[edgel++] = EDGE(x, y, z, false); } for(int i=0; i ) { scanf("%d%d%d", &x, &y, &z); addEdge(x, y, z); edge[edgel++] = EDGE(x, y, z, true); } Tarjan(); dfs(s); initEdge(); initLink(); clr(indegree, 0); for(int i=0; i
) { if(visitable[edge[i].u] && visitable[edge[i].v]) { addEdge(edge[i].u, edge[i].v, edge[i].w); if(edge[i].flag) { ++ indegree[belong[edge[i].v]]; addLink(belong[edge[i].v], edge[i].v); } else { addEdge(edge[i].v, edge[i].u, edge[i].w); } } } stack<int> zeroDegree; priority_queue int,int> > que; clr(vis, false); clr(tag, false); clr(dis, 0x3f); dis[s] = 0; que.push(make_pair(0, s)); while(!que.empty() || !zeroDegree.empty()) { if(que.empty()) { int x = zeroDegree.top(); zeroDegree.pop(); for(int i=lh[x]; ~i; i=lnxt[i]) { int y = lv[i]; if(!vis[y]) { vis[y] = true; que.push(make_pair(-dis[y], y)); } } } else { int x = que.top().second; que.pop(); if(tag[x]) continue; tag[x] = true; for(int i=h[x]; ~i; i=nxt[i]) { int y = v[i]; if(!tag[y] && dis[y] > dis[x] + w[i]) { dis[y] = dis[x] + w[i]; if(belong[x] == belong[y]) { que.push(make_pair(-dis[y], y)); } } if(belong[x] != belong[y]) { -- indegree[belong[y]]; if(indegree[belong[y]] == 0) { zeroDegree.push(belong[y]); } } } } } for(int i=1; i<=n; i++) { if(visitable[i]) { printf("%d\n", dis[i]); } else { puts("NO PATH"); } } } return 0; }
/* 算法提高 最小方差生成树 问题描述 给定带权无向图,求出一颗方差最小的生成树。 输入格式 输入多组测试数据。第一行为N,M,依次是点数和边数。接下来M行,每行三个整数U,V,W,代表连接U,V的边,和权值W。保证图连通。n=m=0标志着测试文件的结束。 输出格式 对于每组数据,输出最小方差,四舍五入到0.01。输出格式按照样例。 样例输入 4 5 1 2 1 2 3 2 3 4 2 4 1 1 2 4 3 4 6 1 2 1 2 3 2 3 4 3 4 1 1 2 4 3 1 3 3 0 0 样例输出 Case 1: 0.22 Case 2: 0.00 数据规模与约定 1<=U,V<=N<=50,N-1<=M<=1000,0<=W<=50。数据不超过5组。 */ //无答案求解答
/* 算法提高 邮票面值设计 问题描述 给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤13)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAX,使在1~MAX之间的每一个邮资值都能得到。 例如,N=3,K=2,如果面值分别为1分、4分,则在1分~6分之间的每一个邮资值都能得到(当然还有8分、9分和12分);如果面值分别为1分、3分,则在1分~7分之间的每一个邮资值都能得到。可以验证当N=3,K=2时,7分就是可以得到的连续的邮资最大值,所以MAX=7,面值分别为1分、3分。 输入格式 一行,两个数N、K 输出格式 两行,第一行升序输出设计的邮票面值,第二行输出“MAX=xx”(不含引号),其中xx为所求的能得到的连续邮资最大值。 样例输入 3 2 样例输出 1 3 MAX=7 */ #include#define M 500 int a[20],f[M],ans[20]; int N,K,MAX,g=1<<29; void DFS(int k,int s){ int i,j,t[M]; if (k==K) { if (s>=MAX) for (MAX=s,i=1;i<=K;i++) ans[i]=a[i]; return; } for (i=0;i ) t[i]=f[i]; for (i=a[k]+1;i<=s;i++) { for (j=0;j ) if (f[j]+1 i]) f[j+i]=f[j]+1; for (j=s;f[j]<=N;j++); a[k+1]=i; DFS(k+1,j); for (j=0;j t[j]; }} int main(){ int i; scanf("%d%d",&N,&K); a[1]=1; for (i=1;i<=N;i++) f[i]=i; for (;i ) f[i]=g; DFS(1,N+1); for (i=1;i<=K;i++) printf("%d ",ans[i]); printf("\nMAX=%d",MAX-1); return 0; }
/* 算法提高 子集选取 问题描述 一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得它们的交集的元素个数为K,求取法的方案数,答案模1000000007。 输入格式 输入一行两个整数N,K。 输出格式 输出一个整数表示答案。 样例输入 3 2 样例输出 6 数据规模和约定 1 <= K <= N <= 10 ^ 6。 */ //I Have No Answer
/* 算法提高 冒泡排序计数 考虑冒泡排序的一种实现。 bubble-sort (A[], n) > round = 0 > while A is not sorted > > round := round + 1 > > for i := 1 to n - 1 > > > if (A[i] > A[i + 1]) > > > > swap(A[i], A[i + 1]) 求1 .. n的排列中,有多少个排列使得A被扫描了K遍,亦即算法结束时round == K。 答案模20100713输出。 输入格式 输入包含多组数据。每组数据为一行两个整数N,K。 输出格式 对每组数据,输出一行一个整数表示答案。 样例输入 3 3 0 3 1 3 2 样例输出 1 3 2 数据规模和约定 T <= 10 ^ 5。 1 <= K < N < 10 ^ 6。 */ #define OUTPUT_PRECISION "%.2f" #define LF_PRECISION 10 #define INT_64_MOD "%I64d" #define UNSIGNED_64_MOD "%I64u" #include#include #include #include #include #include #include #include #include #include #include #include
/* 算法提高 递归倒置字符数组 问题描述 完成一个递归程序,倒置字符数组。并打印实现过程 递归逻辑为: 当字符长度等于1时,直接返回 否则,调换首尾两个字符,在递归地倒置字符数组的剩下部分 输入格式 字符数组长度及该数组 输出格式 在求解过程中,打印字符数组的变化情况。 最后空一行,在程序结尾处打印倒置后该数组的各个元素。 样例输入 Sample 1 5 abcde Sample 2 1 a 样例输出 Sample 1 ebcda edcba edcba Sample 2 a */ #include#include<string.h> void digui(char *c,int top,int end) { char tmp; if(top==end) return; if(top<end) { tmp=c[top]; c[top]=c[end]; c[end]=tmp; puts(c); digui(c,top+1,end-1); } } int main(void) { char c[1000]; int n; scanf("%d",&n); getchar(); gets(c); digui(c,0,n-1); printf("\n"); puts(c); return 0; }
/* 算法提高 立方体截断问题 问题描述 如右图所示,这是一个空心正方体(请想象用纸糊出来的正方体),每条棱的编号如图所示 (图在http://166.111.138.150/fop/attach/cube.jpg)。 考虑剪开若干条棱,请判断正方体是否会被剪成分开(即判断正方体是否会被分割成不少于2个部分)。 输入格式 本题包括多组数据。 第一行输入一个N,表示数据组数。 对于每一组数据,都包括两行。 第一行输入一个n,表示总共剪开了n条棱。 第二行有n个数,每个数表示剪开的棱的编号。(输入保证每条棱出现次数不超过1) 输出格式 对于每一组输入,输出一行。 若正方体会被分割成不少于2个部分,则输出“Yes”,否则输出“No”(均不包括引号)。 样例输入 5 4 1 2 3 4 6 1 2 5 7 11 12 3 1 4 5 6 1 3 4 5 9 12 12 1 2 3 4 5 6 7 8 9 10 11 12 样例输出 Yes Yes No No Yes */ #define OUTPUT_PRECISION "%.2f" #define LF_PRECISION 10 #define INT_64_MOD "%lld" #define UNSIGNED_64_MOD "%llu" //#pragma comment(linker,"/STACK:102400000,102400000") #include#include #include #include #include #include #include #include #include #include #include #include