A题 RPNF
悲了个催,这种题一直是令我纠结的一种题,表达式求值。。。应该找个时间把这类的正解学下,不能总是现场YY。。。一个堆栈操作的过程,
1.遇到字母直接输出
2.遇到运算符或者左括号op,从栈顶开始,依次与op比较,若优先级大于op,则出栈输出,直到栈为空或者栈顶操作符优先级小于op或者栈顶为'('然后op进栈
3.遇到')',一直出栈,直到栈顶为'('这样就把问题完美解决了代码:
#include <stdio .h>
#include <ctype .h>
#define N 300
char st[N],stack[N];
int priority(char op)
{
switch(op)
{
case '+':return 0;
case '-':return 1;
case '*':return 2;
case '/':return 3;
case '^':return 4;
default:return 5;
}
}
bool cmp(char op1,char op2)
{
return priority(op1)>=priority(op2);
}
int main()
{
int t,i,top;
scanf("%d",&t);
while(t--)
{
scanf("%s",st);
top=0;
for(i=0;st[i];i++)
{
if(isalpha(st[i]))putchar(st[i]);
else
{
if(st[i]==')')
{
while(top&&stack[top]!='(')putchar(stack[top--]);
top--;
}
else
{
while(top&&stack[top]!='('&&cmp(stack[top],st[i]))putchar(stack[top--]);
stack[++top]=st[i];
}
}
}
while(top)putchar(stack[top--]);
puts("");
}
return 0;
}
B题 Default Password
o(∩∩)o...哈哈,大水题,让所有人都能happy的过掉,但要比手速。。水题刷刷更健康~~~~
#include <iostream>
using namespace std;
int main()
{
string st;
while(cin>>st)
{
if(st=="wujiawei")cout< <"hit";else cout <<"lose";
cout<<endl;
}
return 0;
}
C题Censorship
额,对题意有些疑问,样例没看懂,感觉第三个样例答案应该是3有空再研究。。。C题The Final Battle of Daydream
题意:给出1..n中的n-2个数,输出少了的两个数
比赛时内存给了1M,但是数据范围是300,000
挂在oj的题上显示给的内存是64M,应该是出问题了吧。。。
起初我就是开了个布尔数组,但是一直超内存,也就超一点点,眼看着别人一个个AC,心里那个滋味啊。。。。
后来看到最下面一行PS. because of the limit memory, iostream is not recommanded.
然后顿悟,去掉了#include<iostream>,然后就AC了
这么做绝对是水过,算一下内存:sizeof(bool)得到1,也就是1个字节,300,000B, 不知道hoj是否算的是字节,问下1+学长
正确的做法是根据给出的数列出两个方程组成方程组,解出答案
a+b=sum(n)-sum(left)
a^2+b^2=sum(n^2)-sum(left^2)
然后解出a和b
正解:
改编自OnePlus学长空间里的解题报告
#include <cstdio>
#include <cstring>
#include <cmath>
#define sqr(x) ((x)*(x))
#define PRINT(x) cout < <(#x)<<" "<<x<<endl;
using namespace std;
int main() {
double n;
while(scanf("%lf",&n)==1){
double N = 0.0, M = 0.0;
for(double i = 1; i <= n; i ++ ) {
N = N + i;
M = M + sqr(i);
}
N = ( 1 + n ) * n / 2;
M = ( n + 1 ) * ( n*2+1)*n/6;
for(int i = 2; i < n; i ++) {
double x; scanf( "%lf", &x );
N = N - x; M = M - sqr(x);
}
double delta = sqrt(2.0 * M - sqr(N));
//printf( "TEST %.10lf %.10lf %.10lf\n", N, M, delta);
double x = 0.5 * (N - delta), y = 0.5 * (N + delta);
printf( "%.0lf %.0lf\n", x, y );
}
return 0;
}
水解:
#include <stdio .h>
#include <string .h>
#define N 300001
bool f[N];
int main()
{
int n,i,a,tot;
while(scanf("%d",&n)==1)
{
memset(f,0,sizeof(f));
tot=0;
for(i=0;i<n -2;i++)
{
scanf("%d",&a);
f[a]=1;
}
for(i=1;i<=n;i++)
if(!f[i])
{
if(tot)putchar(' ');
tot++;
printf("%d",i);
}
puts("");
}
return 0;
}
E题Costume Party
数学+搜索题
dfs找染色方案,每找出一种染色方案,使用的颜色总数为m1,则ans += A(m,m1)
#include <iostream>
#define N 13
using namespace std;
int tot_edge,n,m,ans;
int MOD=9999997;
struct data
{
int v;
data*next;
}*adj[N],edge[N*N*2];
int visit[N],visitcol[N];
void push_edge(int u,int v)
{
edge[tot_edge].v=v;
edge[tot_edge].next=adj[u];
adj[u]=&edge[tot_edge++];
}
long long a(int n,int m)
{
long long ans=1;
while(m--)
{
ans=ans*n%MOD;
n--;
}
return ans;
}
void dfs(int k)
{
int i;
if(k==n)
{
int totcol=0;
for(i=1;i< =n;i++)
if(visitcol[i])totcol++;
if(totcol<=m)ans=(ans+a(m,totcol))%MOD;
return;
}
data *temp=adj[k];
bool color[N]={false};
while(temp)
{
if(visit[temp->v])
color[visit[temp->v]]=true;
temp=temp->next;
}
for(i=1;i< =n;i++)
if(!color[i]&&visitcol[i])
{
visit[k]=i;
dfs(k+1);
}
for(i=1;i<=n;i++)
if(!visitcol[i])break;
if(i<=n)
{
visit[k]=i;
visitcol[i]=1;
dfs(k+1);
visitcol[i]=0;
}
visit[k]=0;
}
int main()
{
int k,a,b,i,cas=1;
while(scanf("%d %d %d",&m,&n,&k)==3)
{
tot_edge=0;
memset(adj,0,sizeof(adj));
for(i=0;i<k;i++)
{
scanf("%d %d",&a,&b);
a--;
b--;
push_edge(a,b);
push_edge(b,a);
}
memset(visit,0,sizeof(visit));
memset(visitcol,0,sizeof(visitcol));
ans=0;
dfs(0);
printf("Case #%d\n%d\n",cas++,ans);
}
return 0;
}
F题Go Home
我用spfa做的,保留了个二维的读列,但是比较慢,0.22s
看了OnePlus学长博客的<a href="http://www.oneplus.info/archives/230">解题报告</a>,给的做法是堆优化的dijkstra,我用xiaohao2跑了下,0.04s,挺快,直接用的algorithm里的堆(学习下)
OnePlus学长还给了个搜索做的,写的是宽搜,我提交后,时间好慢,0.28s,也许是因为用模板了。。。
看到wdk的只用了0.02s,orz。。。然后问他怎么做到的,他说直接搜索(深搜),看来我水了。。这道题水了。。。搜索竟然比正解快,搜索才是正解。。。。
然后我也写了个深搜,0.01s过掉,回头想了下先前写的spfa,也不过就是宽搜,但是宽搜怎么会比深搜慢那么多倍(都木有用到模板),改了很多次,bfs还是那么慢,纠结。。。。
有谁知道是怎么回事呀。。。
spfa(bfs)写法(变量名有点乱,囧。。。)
#include<stdio .h>
#include<string .h>
#define M 2010
#define N 510
#define NN 250010
struct data
{
int v,co,tm;
data*next;
}*adj[N],edge[M];
int q[NN],f[N][N],cost[NN],visit[N][N];
int C,tot_edge,n;
void push_edge(int u,int v,int c,int t)
{
edge[tot_edge].v=v;
edge[tot_edge].co=c;
edge[tot_edge].tm=t;
edge[tot_edge].next=adj[u];
adj[u]=&edge[tot_edge++];
}
void spfa()
{
q[0]=1;
cost[0]=C;
f[1][C]=0;
int head=-1,tail=1,u,t,c;
data*tmp;
while((head+1)%NN!=tail)
{
head++;
head%=NN;
u=q[head];
c=cost[head];
t=f[u][c][/c];
tmp=adj[u];
visit[u][c][/c]=0;
while(tmp)
{
if(c>=tmp->co&&f[tmp->v][c language="-tmp->co"][/c]>t+tmp->tm)
{
f[tmp->v][c language="-tmp->co"][/c]=t+tmp->tm;
if(tmp->v!=n&&tmp->v!=1&&!visit[tmp->v][c language="-tmp->co"][/c])
{
q[tail]=tmp->v;
cost[tail]=c-tmp->co;
visit[tmp->v][c language="-tmp->co"][/c]=1;
tail++;
tail%=NN;
}
}
tmp=tmp->next;
}
}
}
int main()
{
int T,t,m,i,u,v,c,INF,ans;
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d",&n,&m,&C);
tot_edge=0;
memset(adj,0,sizeof(adj));
for(i=0;i<m ;i++)
{
scanf("%d %d %d %d",&u,&v,&c,&t);
push_edge(u,v,c,t);
push_edge(v,u,c,t);
}
memset(visit,0,sizeof(visit));
memset(f,127,sizeof(f));
ans=INF=f[0][0];
spfa();
for(i=0;i<=C;i++)
if(f[n][i]<ans)ans=f[n][i];
if(ans==INF)puts("-1");
else printf("%d\n",ans);
}
return 0;
}
dfs 写法:
#include<stdio .h>
#include<string .h>
#define N 510
#define M 2010
#define INF 1000000000
int n,tot_edge,ans;
bool visit[N];
struct data
{
int v,c,t;
data * next;
void update(int v,int c,int t,data *k)
{
this->v=v;
this->c=c;
this->t=t;
this->next=k;
}
}edge[M],*adj[N];
void push_edge(int u,int v,int c,int t)
{
edge[tot_edge].update(v,c,t,adj[u]);
adj[u]=&edge[tot_edge++];
}
void dfs(int k,int left,int tim)
{
if(tim>=ans)return;
if(k==n)ans=tim;
else
{
visit[k]=true;
data*temp=adj[k];
while(temp)
{
if(!visit[temp->v]&&left>=temp->c)
dfs(temp->v,left-temp->c,tim+temp->t);
temp=temp->next;
}
visit[k]=false;
}
}
int main()
{
int t,i,a,b,c,m,C,T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d",&n,&m,&C);
tot_edge=0;
memset(adj,0,sizeof(adj));
for(i=0;i<m ;i++)
{
scanf("%d %d %d %d",&a,&b,&c,&t);
push_edge(a,b,c,t);
push_edge(b,a,c,t);
}
ans=INF;
memset(visit,false,sizeof(visit));
dfs(1,C,0);
if(ans==INF)puts("-1");
else printf("%d\n",ans);
}
}
dijkstra+堆优化:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 505;
const int INF = 0x3fffffff;
int first[N];
int cnt = 1;
struct edge
{
int u, v, c, t, next;
} g[N * 4];
void add(int u, int v, int c, int t)
{
g[cnt].u = u;
g[cnt].v = v;
g[cnt].c = c;
g[cnt].t = t;
g[cnt].next = first[u];
first[u] = cnt++;
}
struct node
{
int w, u, t;
bool operator < ( const node &a ) const
{
return t > a.t;
}
};
int n, m, C;
int dis[N][N];
bool used[N][N];
node queue[N * N];
bool relax(int u, int w, int v, int c, int t)
{
if (dis[u][w] + t < dis[v][w + c])
{
dis[v][w + c] = dis[u][w] + t;
return true;
}
return false;
}
void dij(int u)
{
for (int i = 0; i <= n; ++i) for (int j = 0; j <= C; ++j) dis[i][j] = INF;
memset(used, false, sizeof(used));
int tail = 0;
int v, w, c, t;
dis[u][0] = 0;
queue[tail].u = u;
queue[tail].w = 0;
queue[tail].t = 0;
tail++;
make_heap(queue, queue + tail);
while (tail > 0)
{
pop_heap(queue, queue + tail);
tail--;
u = queue[tail].u;
if ( u == n ) break;
w = queue[tail].w;
if ( !used[u][w] )
{
used[u][w] = true;
for (int tmp = first[u]; tmp ; tmp = g[tmp].next)
{
v = g[tmp].v;
c = g[tmp].c;
t = g[tmp].t;
if ( w + c < = C && !used[v][w + c] && relax(u, w, v, c, t) )
{
queue[tail].u = v;
queue[tail].w = w + c;
queue[tail].t = dis[v][w + c];
tail++;
push_heap(queue, queue + tail);
}
}
}
}
return;
}
int main()
{
int cases, u, v, c, t;
scanf("%d", &cases);
while (cases--)
{
memset(first, 0, sizeof(first));
cnt = 1;
scanf("%d %d %d", &n, &m, &C); // n:1~n
for (int i = 0; i < m; ++i)
{
scanf("%d %d %d %d", &u, &v, &c, &t);
add(u, v, c, t);
add(v, u, c, t);
}
dij(1);
int ans = INF;
for (int i = C; i >= 0; --i)
{
if (dis[n][i] != INF)
{
ans = min(ans, dis[n][i]);
}
}
printf("%d\n", ans == INF ? -1 : ans);
}
return 0;
}
G题Alex's Problem
求截面面积。。。。坑爹啊。。。。更坑爹的是学长竟然做下来啦。。。
Alex 的problem很严重啊
没那份耐心去想,此题报告待写。。。
H题Zhou Yi II
二进制转十进制。。。。
#include <iostream>
using namespace std;
int main()
{
char st[100];
int n,i,ans;
while(scanf("%d",&n)==1)
{
getchar();
ans=0;
for(i=0;i<n ;i++)
{
gets(st);
ans<<=1;
if(strcmp(st,"---"))
ans++;
}
printf("%d\n",ans);
}
return 0;
}
Okay,网络赛的报告就写到这,其中两道题待做,会尽快做掉。。。。
就这报告还写了这么长时间。。。。咳咳。。。不过很爽,很久都没安静做题了,这回泡在图书馆一下午+晚上,安安静静的做完这些事,挺好。。。。