您的位置:首页 > 其它

2013 福州大学第十届程序设计竞赛

2013-04-29 22:12 274 查看
A题:中学物理题,直接求就好了;

#include<stdio.h>
#include<string.h>
int main()
{
__int64 cas,s,h,vx,vy;
scanf("%I64d",&cas);
while(cas--)
{
scanf("%I64d%I64d%I64d%I64d",&s,&h,&vx,&vy);
vx=s/vx;
vy=vy*vx-5*vx*vx;
if(vy>=h) puts("good done!");
else puts("poor Merida!");
}
return 0;
}


B题:kmp算法;

#include<stdio.h>
#include<string.h>
char substr[110];
int next[110];
char tolower(char ch)
{
if(ch>='A'&&ch<='Z') return ch-'A'+'a';
return ch;
}
void get(int m)
{
int i=-1,j=0;next[0]=-1;
while(j<m){
if(i==-1||tolower(substr[i])==tolower(substr[j]))
{
i++;j++;
next[j]=i;
}else i=next[i];
}
}
char str[55000];
int kmp(int s,int m,int n)
{
int i=s,j=0;
while(i<n&&j<m){
if(j==-1||tolower(str[i])==tolower(substr[j])){
i++;j++;
}else j=next[j];
}
return j<m?-1:i-m;
}
char des[110];
int main()
{
int i,n,m,k,g;
while(scanf("%s",substr)!=EOF)
{
m=strlen(substr);get(m);
getchar();
gets(des);g=strlen(des);
gets(str);n=strlen(str);
for(i=0;i<n;){
k=kmp(i,m,n);
if(k==-1){
printf("%s",str+i);
i=n;
}else {
for(;i<k;i++) putchar(str[i]);
i=k+m;
for(k=0;k<g;k++) putchar(des[k]);
}
}
putchar('\n');
}
return 0;
}


C题:直接统计

#include<stdio.h>
#include<string.h>
int a[]={1,0,0,0,1,0,1,0,2,1};
int main()
{
int cas,n,sum;
scanf("%d",&cas);
while(cas--)
{
sum=0;
scanf("%d",&n);
while(n) sum+=a[n%10],n/=10;
printf("%d\n",sum);
}
return 0;
}


D题:搜索

/*

 * 题目:吃豆人

 * 题目链接:http://acm.fzu.edu.cn/contest/problem.php?cid=129&sortid=4

 * 题目描述:

 * 地图上有n×m个格子,每格地形可能为空地或者障碍物,吃豆人可以在空地上移动,

 *  吃豆人每移动一格需要1s时间,并且只能朝上下左右四个方向移动,特别的是吃豆人还能吐出舌头,

 *  舌头每移动一格需要0.1s时间,舌头只可以走直线。不必考虑吃豆人转身所需要的时间。

 *  游戏中还有加速道具,一旦得到加速道具,吃豆人就获得2倍移动速度,吐舌头的速度没有增加,

 *  即走1格用0.5s。现在地图上有且只有一颗豆子。游戏中有.代表空地;X表示障碍,吃豆人不能越过障碍;

 *  B代表豆子;S代表加速道具,并且地图上道具总数不超过1个,道具所在的位置为空地,得到道具后立即使用,

 *  道具立即消失,地形变为空地,不能用舌头去取道具;P表示吃豆人,吐舌头的时候吃豆人不能移动。

 *  求最快用多少s吃到豆子,结果保留1位小数?

 * 

 * 解题思路:

 * 和往常用bfs去搜索一条最优的路径的做法一样,这个也可以采用bfs搜索,因为数据范围很小用dfs也可以;

 *  我是用bfs做的,用dp[i][j][s]表示从起点走到(i,j)点且当前速度为s的最短时间,这样不断的去更新所有

 *  点,在每一点上都尝试是否可以吃到豆子,如果可以吃到豆子,则去尝试更新吃豆子的最短时间,这样直到队列为空。

 *  

 *  最后如果可以吃到豆子,输出能吃到豆子的最短时间,否则输出-1;

 *  代码如下:

 */

#include<stdio.h>
#include<string.h>
#include<queue>

using namespace std;

int op[4][2]={1,0,0,1,-1,0,0,-1};
char mat[30][30];
int n,m;
int dp[30][30][15],vis[30][30][15];
void update(int r,int c,int s,int &Min) //判断是否可以吃到豆子,并去更新最短时间
{
int i;
for(i=r+1;i<=n;i++)
if(mat[i][c]!='.'&&mat[i][c]!='S')break;
if(i<=n&&mat[i][c]=='B'&&dp[r][c][s]+(i-r)*2<Min)
Min=dp[r][c][s]+(i-r)*2;
for(i=r-1;i>0;i--)
if(mat[i][c]!='.'&&mat[i][c]!='S')break;
if(i>0&&mat[i][c]=='B'&&dp[r][c][s]+(r-i)*2<Min)
Min=dp[r][c][s]+(r-i)*2;
for(i=c+1;i<=m;i++)
if(mat[r][i]!='.'&&mat[r][i]!='S') break;
if(i<=m&&mat[r][i]=='B'&&dp[r][c][s]+(i-c)*2<Min)
Min=dp[r][c][s]+(i-c)*2;
for(i=c-1;i>0;i--)
if(mat[r][i]!='.'&&mat[r][i]!='S') break;
if(i>0&&mat[r][i]=='B'&&dp[r][c][s]+(c-i)*2<Min)
Min=dp[r][c][s]+(c-i)*2;
}
int bfs(int r,int c) //搜索函数
{
int i,j,x,y,Min=10000000,s,ts,k;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
for(k=1;k<=10;k++)
dp[i][j][k]=100000000;
queue<int> X,Y,S;
vis[r][c][10]=1;dp[r][c][10]=0;
X.push(r);Y.push(c);S.push(10);
while(!X.empty()){
r=X.front();X.pop();
c=Y.front();Y.pop();
s=S.front();S.pop();
update(r,c,s,Min);
for(i=0;i<4;i++) //往4个方向搜
{
ts=s;
x=r+op[i][0];
y=c+op[i][1];
if(x<1||x>n||y<1||y>m||mat[x][y]=='X'||(mat[x][y]=='S'&&s==5)) continue;
if(mat[x][y]=='S') ts=s/2;
if(dp[r][c][s]+s<dp[x][y][ts]){
dp[x][y][ts]=dp[r][c][s]+s;
update(x,y,ts,Min);
if(!vis[x][y][ts]){
vis[x][y][ts]=1;
X.push(x);Y.push(y);S.push(ts);
}
}
}
vis[r][c][s]=0;
}
if(Min==10000000) Min=-1;
return Min;
}
int main()
{
int i,j,sx,sy;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%s",mat[i]+1);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(mat[i][j]=='P'){ sx=i;sy=j;}
sy=bfs(sx,sy);
if(sy<0) printf("-1\n");
else printf("%.1lf\n",sy/10.0);
}
return 0;
}


 

E题:看懂题意的公式后,s(x,m)的范围不会超过1000,所以x的取值范围就在sqrt(n)至sqrt(n)-1000左右,

解释:因为s(x,m)的最大值不会超过1000,当x为(sqrt(n)-1000)以下时,x*(x+s(x,m))<sqrt(n)×sqrt(n)<n;所以就不可能了

枚举几百上千次就好了。

#include<stdio.h>
#include<math.h>
#include<string.h>

#define _LL __int64
#define FM "%I64d"
int m;
_LL F(_LL x)
{
_LL t=x,sum=x*x;
while(x){
sum+=(x%m)*t;x/=m;
}
return sum;
}
int main()
{
int cas;
_LL n,i,l;
scanf("%d",&cas);
while(cas--){
scanf(FM,&n);
scanf("%d",&m);
l=(_LL)sqrt((double)(n+1));i=l-1000;
if(i<=0)i=1;
for(;i<=l;i++)
if(F(i)==n) break;
if(i>l) i=-1;
printf("%d\n",(int)i);
}
return 0;
}

F题:不会

G题:枚举第一条边的长度,统计当第一条边确定时,第二三条边可能的方案数;

三角形的二三条边中,令第二条边慢慢增大,第三条边慢慢减小,所以当第一边确定时的答案就是:

Min(第二条可以增大的最大值,第三条可以减小的最大值,第三条边的上限减去第二条边的下限除以2);

H题:用ac自动机求出母串每一个匹配点的向前的最短匹配距离,然后求出母串每一个点的向前的最大合法长度,取所有中的最大值就是答案;

这题貌似用后缀数组也可以解;

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;

#define N 101000

int ch
[26],cnt,f
,last
,val
,pos
;
struct aho_corasick
{
aho_corasick(){
cnt=0;
memset(ch,0,sizeof(ch));
memset(val,0,sizeof(val));
memset(pos,0,sizeof(pos));
}
int newnode(){ return ++cnt; }
int idx(char c){ return c-'a'; }
void insert(char *s,int n)
{
int root=0,i;
for(i=0;i<n;i++)
{
int u=idx(s[i]);
if(!ch[root][u])ch[root][u]=newnode();
if(i==n-1) val[ch[root][u]]=n;
root=ch[root][u];
}
}
void getfail()
{
queue <int> q;
f[0]=0;
int i,u;
for(i=0;i<26;i++)
{
u=ch[0][i];
if(u){
f[u]=0; q.push(u);last[u]=0;
}
}
while(!q.empty())
{
int r=q.front(); q.pop();
for(i=0;i<26;i++)
{
u=ch[r][i];
if(!u){ ch[r][i]=ch[f[r]][i]; continue; }
q.push(u);
int v=f[r];
while(v&&!ch[v][i]) v=f[v];
f[u]=ch[v][i];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
int find(char *t,int n)
{
int i,j=0,temp;
for(i=0;i<n;i++)
{
int c=idx(t[i]);
//while(j&&!ch[j][c])j=f[j];
j=ch[j][c];
temp=j;
while(temp)
{
if(val[temp]&&(!pos[i]||val[temp]<pos[i]))
pos[i]=val[temp];
temp=last[temp];
}
}
return 0;
}
};
char str[1100000],substr[110];
int main()
{

int i,n,len;
while(scanf("%s",str)!=EOF)
{
len=strlen(str);
scanf("%d",&n);
aho_corasick ac;
for(i=1;i<=n;i++)
{
scanf("%s",substr);
ac.insert(substr,strlen(substr));
}
ac.getfail();
ac.find(str,len);
//for(i=0;i<len;i++)printf("%d",pos[i]);
//printf("\n");
if(!pos[0])pos[0]=2;
for(i=1,n=0;i<len;i++)
{
if(!pos[i])
pos[i]=pos[i-1]+1;
else{
if(pos[i]>i-n+pos
)
pos[i]=i-n+pos
;
n=i;
}
}
//for(i=0;i<len;i++)printf("%d",pos[i]);
//printf("\n");
for(n=i=0;i<len;i++)
if(pos[i]>n) n=pos[i];
printf("%d\n",n-1);
}
return 0;
}

I题:不会
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: