- uva210 模拟
大模拟题,读清题意,想好数据结构,单元测试 - uva514 栈原理
用类似于双指针的操作。 - uva442 表达式解析
表达式解析的常规套路:想好栈中元素,想好元素初值,画自动机 int ans = 0;
int sl = 0, sr = 0;
stack<pair<int,int>> st;
for(auto c:expr)
{
if(isalpha(c))
{
if(sl==0)
{
sl = lef[c], sr = rig[c];
}
else
{
ans += sl * lef[c] * rig[c];
sr = rig[c];
}
}
else if(c=='(')
{
st.emplace(sl,sr);
sl = 0, sr = 0;
}
else if(c==')')
{
int xl = st.top().first, xr = st.top().second; st.pop();
ans += xl*max(xr,sl)*sr;
if(xl) sl=xl;
if(sr==0) sr=xr;
}
}
- uva11988 链表
熟悉std::list的操作 - uva12657
双向链表,很好的一道题,以后可以再写一遍。
加标记,提前保存,函数扩展。
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 500016, MOD = 1000000007;
int pre[M], nxt[M];
inline void link(int x, int y)
{
nxt[x]=y;
pre[y]=x;
}
int main(void)
{
int n,m,kase=0;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;++i)
{
pre[i] = i-1;
nxt[i] = i+1;
}
nxt[0] = 1, pre[n+1] = n;
int inv = 0;
while(m--)
{
int op = read();
if(op==4)
{
inv^=1;
continue;
}
int x = read(), y = read();
int lx = pre[x], ly = pre[y], rx = nxt[x], ry = nxt[y];
if(op<3 && inv) op = 3 - op;
if(op==1 && nxt[x]!=y)
{
link(lx,rx);
link(ly,x);
link(x,y);
}
if(op==2 && pre[x]!=y)
{
link(lx,rx);
link(y,x);
link(x,ry);
}
if(op==3)
{
if(x==pre[y])
{
link(lx,y);
link(y,x);
link(x,ry);
}
else if(y==pre[x])
{
link(ly,x);
link(x,y);
link(y,rx);
}
else
{
link(lx,y);
link(ly,x);
link(y,rx);
link(x,ry);
}
}
}
int cnt = 1;
ll ans = 0;
for(int i=nxt[0];i!=n+1;i=nxt[i])
{
if(cnt^inv) ans += i;
cnt^=1;
}
printf("Case %d: %lld\n",++kase,ans );
}
return 0;
}
- uva 679
算结论题 - uva 122
输入处理 - uva 548 由中序和后序建树,经典题
int n, nxt = 0;
int in_order[M], post_order[M], anti_in[M];
int ans = 0, miamount = INT_MAX, mival = INT_MAX;
struct Node
{
int val;
int amount;
vector<int> son;
}node[M];
int solve(int in_lef, int post_lef, int length)
{
int n_id = nxt++;
node[n_id].val = post_order[post_lef+length-1];
int in_rt = anti_in[node[n_id].val];
int lef_len = in_rt - in_lef, rig_len = length - 1 - lef_len;
if(lef_len) node[n_id].son.push_back(solve(in_lef, post_lef, lef_len));
if(rig_len) node[n_id].son.push_back(solve(in_rt+1, post_lef+lef_len, rig_len));
return n_id;
}
void dfs(int now, int lst)
{
node[now].amount = node[now].val + lst;
if(node[now].son.empty() && (node[now].amount<miamount ||
(node[now].amount == miamount && node[now].val<mival)))
{
ans = now;
miamount = node[now].amount;
mival = node[now].val;
}
for(auto nxt:node[now].son)
dfs(nxt, node[now].amount);
}
inline bool init()
{
nxt = n = 0;
ans = 0;
miamount = mival = INT_MAX;
memset(node,0,sizeof(node));
string tmp;
stringstream sin;
getline(cin,tmp); if(tmp=="") return 0; sin = stringstream(tmp);
while(sin >> in_order[n+1])
++n;
getline(cin,tmp); sin = stringstream(tmp);
for(int i=1;i<=n;++i)
sin >> post_order[i];
return n;
}
int main(void)
{
#ifdef _LITTLEFALL_
freopen("in.txt","r",stdin);
#endif
while(init())
{
for(int i=1;i<=n;++i)
anti_in[in_order[i]] = i;
solve(1,1,n);
dfs(0,0);
printf("%d\n",node[ans].val );
}
return 0;
}
- Uva 839 经典结构,输入,递归,传递引用,返回
- uva 699 递归
- uva 297 四分树
年轻的时候做过这道题,没做出来。
把四分树表示的图像画出来就好了。 - uva572 dfs求连通块
- uva1103 代码结构要明确,dfs函数写一个就行。
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 256, MOD = 1000000007;
const int go[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const char ch[7] = {'W','A','K','J','S','D'};
int mp[M][M],tag[M][M],n,m;
int ans[M*M];
char out[M*M];
void dfs(int i,int j,int co,int st)
{
tag[i][j] = st;
for(int k=0;k<4;++k)
{
int ni = i+go[k][0], nj = j+go[k][1];
if(ni>=0 && ni<=n+1 && nj>=0 && nj<=m+1 && mp[ni][nj]==co && tag[ni][nj]==0)
dfs(ni,nj,co,st);
}
return;
}
int init()
{
scanf("%d%d",&n,&m);
if(n==0) return 0;
m<<=2;
memset(mp,0,sizeof(mp));
memset(tag,0,sizeof(tag));
memset(ans,0,sizeof(ans));
memset(out,0,sizeof(out));
char tmp[64];
for(int i=1;i<=n;++i)
{
scanf("%s",tmp+1);
for(int j=1;tmp[j];++j)
{
int num = isalpha(tmp[j])?tmp[j]-'a'+10:tmp[j]-'0';
for(int k=0;k<4;++k)
mp[i][(j-1)*4+1+k] = (num>>(3-k))&1;
}
}
return 1;
}
int main(void)
{
int kase = 0;
while(init())
{
int bls=0;
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j)
{
if(mp[i][j]==1 && tag[i][j]==0)
dfs(i,j,1,++bls);
}
dfs(0,0,0,-1);
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(mp[i][j]==1)
{
for(int k=0;k<4;++k)
{
int ni=i+go[k][0],nj=j+go[k][1];
if(mp[ni][nj]==0 && tag[ni][nj]==0)
{
++ans[tag[i][j]];
dfs(ni,nj,0,tag[i][j]);
}
}
}
for(int i=1;i<=bls;++i)
out[i]=ch[ans[i]];
sort(out+1,out+bls+1);
printf("Case %d: %s\n",++kase,out+1 );
}
return 0;
}
- uva816 带方向的迷宫
认清问题实质,然后bfs - uva10305 拓扑排序
dfs,把新访问完的放在最前面 - uva10129 欧拉路
- 无向图,欧拉圈:没有奇度数点。
- 无向图,欧拉路:没有奇度数点或只有两个
- 有向图,欧拉圈:所有节点入度=出度
- 有向图,欧拉路:满足上述条件,或者有一节点入度=出度+1且有一节点出度=入度+1,其它节点全部入度=出度。
- 图必须连通(有向图为底图连通)
- uva10562 递归
注意字符集不一定是小写字母,isprint()判断可打印字符(包括空白字符),isgraph()不包括空白字符 - UVA - 12171 Sculpture 离散化,网格与点的转化
- uva1572 建图,判环
以字母+符号为点,正方形看成边,建立一个有向图。注意每条边的起点不变,终点变成它的共轭。当且仅当图中有环时输出yes。set<int> edg[M];
int vis[M];
bool dfs(int u)
{
vis[u] = 1;
for(auto v:edg[u])
{
if(vis[v]==1)
return false;
else if(vis[v]==0)
if(!dfs(v)) return false;
}
vis[u] = 2;
return true;
}
bool noloop()
{
for(int i=0;i<52;++i)
if( !vis[i] && !dfs(i) ) return false;
return true;
}
int init()
{
for(int i=0;i<M;++i)
edg[i].clear();
memset(vis,0,sizeof(vis));
int n;
if(scanf("%d",&n)==-1) return 0;
char tmp[10];
for(int i=0;i<n;++i)
{
scanf("%s",tmp);
for(int id1=0;id1<4;++id1)
{
for(int id2=id1+1;id2<4;++id2) if(tmp[id1*2]!='0' && tmp[id2*2]!='0')
{
int u = (tmp[id1*2]-'A')*2 + (tmp[id1*2+1]=='+');
int v = (tmp[id2*2]-'A')*2 + (tmp[id2*2+1]=='+');
edg[u].insert(v^1), edg[v].insert(u^1);
}
}
}
return n;
}
int main(void)
{
#ifdef _LITTLEFALL_
freopen("in.txt","r",stdin);
#endif
while(init())
{
printf("%s\n",noloop()?"bounded":"unbounded" );
}
return 0;
}
- uva1599 bfs
给一无向图,每条边都有一个权值。求起点到终点的一条路径,要求经过的边数最小,且边权序列的字典序最小。
反向bfs一遍,然后从起点开始逐距离把所有边权最小的点的记录下来,每次仅从边权最小的点向后转移。注意有自环或重边,所以需要对记录去重,否则记录数量会变成指数。int n,m;
struct Node{
int fst;
int dis;
}nod[N];
struct Edge{
int pnt,nxt,pri;
}edg[M];
int ect;
void addEdge(int u,int v,int p)
{
edg[++ect].pnt = v;
edg[ect].pri = p;
edg[ect].nxt = nod[u].fst;
nod[u].fst = ect;
}
set<int> per[N];
int init()
{
if(scanf("%d%d",&n,&m)==-1) return 0;
memset(nod,-1,sizeof(nod));
memset(edg,0,sizeof(edg));
for(int i=0;i<N;++i) per[i].clear();
ect = 0;
while(m--)
{
int a=read(),b=read(),c=read();
addEdge(a,b,c);
addEdge(b,a,c);
}
return 1;
}
void bfs(int st)
{
queue<int> q;
nod[st].dis = 0;
q.push(st);
while(!q.empty())
{
int u = q.front(); q.pop();
for(int vd=nod[u].fst; ~vd; vd=edg[vd].nxt)
{
int v = edg[vd].pnt;
if(nod[v].dis == -1)
{
nod[v].dis = nod[u].dis+1;
q.push(v);
}
}
}
}
int main(void)
{
#ifdef _LITTLEFALL_
freopen("in.txt","r",stdin);
#endif
while(init())
{
bfs(n);
int tot = nod[1].dis;
printf("%d\n",tot );
per[tot].insert(1);
for(int dis = tot; dis; --dis)
{
int ans = MOD;
for(auto u:per[dis])
for(int vd=nod[u].fst; ~vd; vd=edg[vd].nxt)
if(nod[ edg[vd].pnt ].dis == dis-1)
ans = min(ans, edg[vd].pri);
for(auto u:per[dis])
for(int vd=nod[u].fst; ~vd; vd=edg[vd].nxt)
{
int v = edg[vd].pnt;
if(nod[v].dis == dis-1 && edg[vd].pri==ans)
per[dis-1].insert(v);
}
printf("%d%c",ans,dis==1?'\n':' ' );
}
}
return 0;
}
- uva506 大模拟 题目没给数据范围,应该在10000左右.
- uva11853 简单计算几何,dfs
正方形内有n个圆形障碍物,问能否从左边界走到右边界,如果可以,求最北边的进入点和离去点。
把每个障碍物视作一个点,如果两个圆相交,那么它们有边相连。当且仅当与上边界相交的圆连通的圆与下边界相交时,无法走通。能走通时,最北边的进入点就是与上边界连通的圆与左边界的最南方交点,离去点同理。int n, ect;
struct Node{
int fst;
int x,y,r;
int vis;
}nod[M];
struct Edge{
int nxt,pnt;
}edg[M];
inline void addEdge(int a, int b)
{
edg[++ect].pnt = b;
edg[ect].nxt = nod[a].fst;
nod[a].fst = ect;
}
int fail = 0;
double lin = 1000, lout = 1000;
void dfs(int u)
{
nod[u].vis = 1;
for(int vd=nod[u].fst; vd; vd=edg[vd].nxt)
{
int v = edg[vd].pnt;
if(!nod[v].vis) dfs(v);
}
int r = nod[u].r, x = nod[u].x, y = nod[u].y;
if(y-r<=0) fail = 1;
if(x-r<=0)
lin = min(lin,y-sqrt(r*r-x*x));
if(x+r>=1000)
lout = min(lout,y-sqrt(r*r-(1000-x)*(1000-x)));
}
int init()
{
n = ect = fail = 0;
lin = lout = 1000.0;
memset(nod,0,sizeof(nod));
memset(edg,0,sizeof(edg));
if(scanf("%d",&n)==-1) return 0;
for(int i=1;i<=n;++i)
{
nod[i].x = read();
nod[i].y = read();
nod[i].r = read();
}
for(int i=1;i<=n;++i)
{
int ax = nod[i].x, ay = nod[i].y, ar=nod[i].r;
for(int j=i+1;j<=n;++j)
{
int bx = nod[j].x, by = nod[j].y, br=nod[j].r;
if((ax-bx)*(ax-bx)+(ay-by)*(ay-by)<=(ar+br)*(ar+br))
addEdge(i,j), addEdge(j,i);
}
}
return 1;
}
int main(void)
{
#ifdef _LITTLEFALL_
freopen("in.txt","r",stdin);
#endif
while(init())
{
for(int i=1;i<=n;++i)
if(!nod[i].vis && nod[i].y+nod[i].r>=1000)
dfs(i);
if(fail)
printf("IMPOSSIBLE\n");
else
printf("0.00 %.2f 1000.00 %.2f\n",lin,lout );
}
return 0;
}