[cpp]
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 1000000007
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int n;
char s[105];
int ss[705];
int main()
{
int t;
scanf("%d",&t);
getchar();
while(t--)
{
gets(s);
int l = strlen(s);
int ll = 0;
int ma = 0;
int a = s[0] - '0';
ss[0] = a;
ma = a;
ll++;
int b;
for(int i=1;i<l;i++)
{
a = s[i-1] - '0';
b = s[i] - '0';
ma = max(ma,b);
if(b == a)
{
ss[ll] = b;
ll++;
}
if(b > a)
{
int c = a + 1;
do
{
ss[ll] = c;
c++;
ll++;
}while(c <= b);
}
if(b < a)
{
int c = a - 1;
do
{
ss[ll] = c;
c--;
ll++;
}while(c >= b);
}
}
for(int i = ma;i >=1;i--)
{
for(int j=0;j<ll;j++)
{
if(i > ss[j]) printf("*");
else printf("+");
}
printf("\n");
}
}
return 0;
}
E.Social Holidaying
二分圖匹配,題意是給你兩個序列,要求A序列中最多有多少對數和為B序列中的數,且A序列中的數每個只能用一次,B序列的數可以無限次出現。
思路:可以將A序列中所有能組成的可能全都組合起來,如果B序列中有出現就開始搜索,把所有情況都搜出來。
[cpp]
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 1000000007
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
map<long long,int>s;
vector<int>p[1001];
int vis[1001],tmp[1001];
long long x[1001],y;
int f(int j)
{
int i,q;
for(i=0;i<p[j].size();++i)
{
q=p[j][i];
if(vis[q]==0)
{
vis[q]=1;
if(tmp[q]==0||f(tmp[q])==1)
{
tmp[q]=j;
return 1;
}
}
}
return 0;
}
int main()
{
int t,i,j,sum,n,m;
scanf("%d",&t);
while(t--)
{
s.clear();
scanf("%d%d",&n,&m);
for(i=0;i<n;++i)
{
scanf("%lld",&x[i]);
}
for(i=0;i<m;++i)
{
scanf("%lld",&y);
s[y]=1;
}
for(i=0;i<n;++i)
{
p[i].clear();
}
sum=0;
for(i=0;i<n;++i)
{
for(j=0;j<n;++j)
{
if(i==j)
{
continue;
}
if(s[x[i]+x[j]]==1)
{
p[i].push_back(j);
}
}
}
mem(tmp,0);
for(i=0;i<n;++i)
{
mem(vis,0);
if(f(i)==1)
{
sum++;
}
}
printf("%d\n",sum/2);
}
return 0;
}
G.Writings on the Wall
字符串問題,問的是前後兩個字符串最多能重合部分幾次。
方法有兩種:kmp和hash
KMP寫法:
[cpp]
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
//#define N 1000000007
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
#define N 50005
char a[N];
char b[N];
int next[N];
int l1,l2;
void update()
{
next[0] = -1;
int i=0,j=-1;
while(i<l2)
{
while(j>=0&&b[i]!=b[j])
{
j=next[j];
}
i++;
j++;
next[i]=j;
}
}
int main()
{
int t,i,j,ans;
scanf("%d",&t);
while(t--)
{
scanf("%s%s",a,b);
l1=strlen(a);
l2=strlen(b);
update();
i=0;
j=0;
while(i<l1)
{
while(j>=0&&a[i]!=b[j])
{
j=next[j];
}
i++;
j++;
if(j==l2&&i<l1)
{
j=next[j];
}
}
ans=0;
while(j>=0)
{
j=next[j];
ans++;
}
printf("%d\n",ans);
}
return 0;
}
HASH寫法:
[cpp]
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#include <queue>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int main()
{
int i,j,l1,l2,t,sum;
long long x,y,z;
char a[50001],b[50001];
RD(t);
while(t--)
{
scanf("%s%s",a,b);
l1=strlen(a);
l2=strlen(b);
i=l1-1;
j=0;
z=1;
x=0;
y=0;
sum=1;
while(i>=0&&j<l2)//hash過程
{
x+=z*(a[i]-'a');
z*=33;
y*=33;
y+=(b[j]-'a');
i--;
j++;
if(x==y)
{
sum++;
}
}
printf("%d\n",sum);
}
return 0;
}
H.Robotic Traceur
最短路,我們悲劇地居然一直TLE,後來才發現BFS,SPFA,甚至連暴搞都可以過。。。
[cpp]
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#include <queue>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
struct xl
{
double x,y;
}v[1001];
double dis(int i, int j)
{
return sqrt((v[i].x-v[j].x)*(v[i].x-v[j].x)+(v[i].y-v[j].y)*(v[i].y-v[j].y));
}
int main()
{
int t,n,s,tmp,i,id[1001],l[1001],w,res;
double p,q;
RD(t);
while(t--)
{
scanf("%d%d%d%lf%lf",&n,&s,&tmp,&p,&q);
p+=q;
FOR(1,n,i)
{
scanf("%lf%lf",&v[i].x,&v[i].y);
id[i]=-1;
}
id[s]=0;
l[0]=s;
w=1;
res=0;
while(res<w)
{
s=l[res];
FOR(1,n,i)
{
if(id[i]<0&&dis(s,i)<p+1e-6)
{
id[i]=id[s]+1;
l[w++]=i;
if(i==tmp)
{
break;
}
}
}
res++;
}
if(id[tmp]>=0)
{
printf("%d\n",id[tmp]);
}
else
{
printf("Impossible\n");
}
}
return 0;
}
I.Shortest Leash
應該是一道dp題,它要求狗可以選擇多個向量的正負方向走,問最遠能與遠點的距離為多少。。。
我是用隨機算法過的,目的在於將所有的向量打亂,使其在加上向量時,能夠會在一次中找到正解。
[cpp]
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
using namespace std;
struct xl
{
double x,y;
} p[101],q,l,r;
double dis(xl a)
{
return sqrt(a.x*a.x+a.y*a.y);
}
int main()
{
int t,i,j,z[101];
double ans;
while(scanf("%d",&t))
{
if(t==0)
{
break;
}
for(i=0; i<t; ++i)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
ans=0;
for(j=0;j<=10000;++j)
{
random_shuffle(p,p+t);//隨機打亂數組
q.x=0;
q.y=0;
for(i=0; i<t; ++i)
{
l=q;
r=q;
l.x+=p[i].x;
l.y+=p[i].y;
r.x-=p[i].x;
r.y-=p[i].y;
if(dis(l)>dis(r))
{
q=l;
}
else
{
q=r;
}
ans=max(ans,dis(q));
}
}
printf("%.3f\n",ans);
}