A、排序
其实这题的话不能乱YY,仔细看下提供的sort代码可以发现其实就是对奇数位的数以及偶数位的数字分别进行排序,那我们只要输入的同时按奇偶位存下数字然后排序与原数组排序的对比就可以了。
代码:
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
#include <cctype>
#include <numeric>
#include <cstring>
#include <climits>
#include <utility>
#include <stack>
using namespace std;
int a[100005];
vector <int> v,w;
bool f;
void init()
{
f=true;
v.clear();
w.clear();
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
int n;
while(scanf("%d",&n)==1)
{
init();
for(int i=0; i<n; ++i)
{
scanf("%d",a+i);
if(f)
{
v.push_back(a[i]);
f=!f;
}
else
{
w.push_back(a[i]);
f=!f;
}
}
sort(v.begin(),v.end());
sort(w.begin(),w.end());
sort(a,a+n);
bool fs=false;
int cnt,cntt;
cnt=cntt=0;
f=true;
for(int i=0; i<n; ++i)
{
if(f)
{
fs=(v[cnt++]==a[i])?false:true;
f=!f;
}
else
{
fs=(w[cntt++]==a[i])?false:true;
f=!f;
}
if(fs)break;
}
if(fs)puts("NO");
else puts("YES");
}
return 0;
}
B、Search For The Golden
这是一题搜索题BFS、DFS应该都能过(因为数据量不大~) ,思路大概就是先从起点去拿钥匙 不开门 其实如果直接判能不能开门也是可以的 我就懒得改了-- 然后再去搜整张图 要注意拿到钥匙后就拿到了 has++递归回来之后 不要再减回去 因为你已经能拿到了这把钥匙为什么还要放下来退回去??其他就没什么坑了~
代码:
#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <climits>
#include <utility>
using namespace std;
int n,m,ex,ey,sx,sy;
char mp[25][25];
int dirx[]= {0,0,1,-1};
int diry[]= {1,-1,0,0}; //right left up down
bool vis[25][25];
bool was[25][25];
struct point
{
int has;
int total;
} p[15];
bool dfs(int x,int y)
{
if(x==ex&&y==ey)return true;
for(int i=0; i<4; ++i)
{
int nx=x+dirx[i];
int ny=y+diry[i];
if(nx<0||nx>=n||ny<0||ny>=m)continue;
if(mp[nx][ny]>='A'&&mp[nx][ny]<='E')continue;
if(mp[nx][ny]!='X'&&!vis[nx][ny])
{
vis[nx][ny]=true;
if(dfs(nx,ny))return true;
vis[nx][ny]=false;
}
}
return false;
}
bool dfsall(int x,int y)
{
if(mp[x][y]=='G')return true;
for(int i=0; i<4; ++i)
{
int nx=x+dirx[i];
int ny=y+diry[i];
if(nx>=0&&nx<n&&ny>=0&&ny<m&&!vis[nx][ny]&&mp[nx][ny]!='X')
{
if(mp[nx][ny]=='.')
{
vis[nx][ny]=true;
if(dfsall(nx,ny))return true;
vis[nx][ny]=false;
}
else if(mp[nx][ny]=='G')
{
if(dfsall(nx,ny))return true;
}
else if(mp[nx][ny]>='a'&&mp[nx][ny]<='e')
{
if(!was[nx][ny])
{
was[nx][ny]=true;
p[mp[nx][ny]-'a'].has++;
vis[nx][ny]=true;
if(dfsall(nx,ny))return true;
vis[nx][ny]=false;
}
else
{
vis[nx][ny]=true;
if(dfsall(nx,ny))return true;
vis[nx][ny]=false;
}
}
else if(mp[nx][ny]>='A'&&mp[nx][ny]<='E')
{
if(p[mp[nx][ny]-'A'].has==p[mp[nx][ny]-'A'].total&&p[mp[nx][ny]-'A'].total)
{
vis[nx][ny]=true;
if(dfsall(nx,ny))return true;
vis[nx][ny]=false;
}
else continue;
}
}
}
return false;
}
void init()
{
memset(was,false,sizeof(was));
memset(p,0,sizeof(p));
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
while(scanf("%d%d",&n,&m)==2)
{
if(n==0&&m==0)break;
init();
for(int i=0; i<n; ++i)
{
scanf("%s",&mp[i]);
for(int j=0; j<m; ++j)
{
if(mp[i][j]>='a'&&mp[i][j]<='e')p[mp[i][j]-'a'].total++;
if(mp[i][j]=='S')
{
sx=i;
sy=j;
}
}
}
for(int i=0; i<n; ++i)
{
for(int j=0; j<m; ++j)
{
if(mp[i][j]>='a'&&mp[i][j]<='e')
{
memset(vis,false,sizeof(vis));
vis[sx][sy]=true;
ex=i;
ey=j;
if(dfs(sx,sy))
{
p[mp[i][j]-'a'].has++;
was[i][j]=true;
}
}
}
}
memset(vis,false,sizeof(vis));
vis[sx][sy]=true;
if(dfsall(sx,sy))puts("YES");
else puts("NO");
}
return 0;
}
C、最大覆盖
其实这一题不算是一个计算几何的问题,主要是一个想法题,可以采用类似扫描线的方式。令一条线段头为true尾部则为false,所以我们可以结构体对其排序(具体见代码),然后来一个点true则+1,否则-1,过程更新ans,取最大值。
代码:
#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <climits>
using namespace std;
struct point {
int num;
bool f;
}p[100005*2];
bool cmp(point a,point b){
if(a.num!=b.num)
return a.num<b.num;
return a.f>b.f;
}
int main()
{
//freopen("data5.in","r",stdin);
//freopen("data5.out","w",stdout);
int n,a,b,cnt;
while(scanf("%d",&n)==1)
{
cnt=0;
for(int i=0;i<n;++i){
scanf("%d%d",&a,&b);
p[cnt].num=a;
p[cnt++].f=true;
p[cnt].num=b;
p[cnt++].f=false;
}
sort(p,p+cnt,cmp);
int ans=0,tmp=0;
for(int i=0;i<cnt;++i){
if(p[i].f){
tmp++;
ans=max(ans,tmp);
}else tmp--;
}
printf("%d\n",ans);
}
return 0;
}
D、数独
好吧,其实以为E会爆零结果D爆了零--,其实就是一个精确覆盖的问题,我们可以采用DL算法(舞蹈链算法)+X算法(其实就是一个DFS),然后套个模板+乱搞=AC
如果是9*9的数独是可以直接DFS的!
给个直接DFS 9*9数独的:
#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <climits>
#include <utility>
#include <stack>
using namespace std;
int n,M;
int mp[25][25];
bool visH[25][25];
bool visL[25][25];
bool visK[25][25][25];
int f;
void dfs(int pos)
{
if(pos==n*n)
{
f++;
return;
}
int x=pos/n;
int y=pos%n;
if(!mp[x][y])
for(int i=1; i<=n; ++i)
{
if(!visH[x][i]&&!visL[y][i]&&!visK[x/M][y/M][i])
{
mp[x][y]=i;
visH[x][i]=true;
visL[y][i]=true;
visK[x/M][y/M][i]=true;
dfs(pos+1);
mp[x][y]=0;
visH[x][i]=false;
visL[y][i]=false;
visK[x/M][y/M][i]=false;
}
}
else dfs(pos+1);
return;
}
int main()
{
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(scanf("%d",&n)==1)
{
M=int(sqrt(n));
memset(visH,false,sizeof(visH));
memset(visL,false,sizeof(visL));
memset(visK,false,sizeof(visK));
f=0;
for(int i=0; i<n; ++i)
{
for(int j=0; j<n; ++j)
{
scanf("%d",&mp[i][j]);
}
}
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
if(mp[i][j]){
visH[i][mp[i][j]]=true;
visL[j][mp[i][j]]=true;
visK[i/M][j/M][mp[i][j]]=true;
}
}
}
dfs(0);
if(f)puts("Yes");
else puts("No");
}
return 0;
}
下面是本题DLX的代码:
#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <strstream>
#include <map>
#include <set>
#include <queue>
#include <climits>
#include <utility>
using namespace std;
struct DLX
{
const static int maxn=20010;
int n,sz;
int S[maxn];
int row[maxn],col[maxn];
int L[maxn],R[maxn],U[maxn],D[maxn];
int ansd,ans[maxn];
void init(int n)
{
this->n=n;
for(int i=0; i<=n; ++i)
{
U[i]=i;
D[i]=i;
L[i]=i-1;
R[i]=i+1;
}
R[n]=0;
L[0]=n;
sz=n+1;
memset(S,0,sizeof(S));
}
void addRow(int r,vector <int> columns)
{
int first=sz;
for(int i=0; i<columns.size(); ++i)
{
int c=columns[i];
L[sz]=sz-1;
R[sz]=sz+1;
D[sz]=c;
U[sz]=U[c];
D[U[c]]=sz;
U[c]=sz;
row[sz]=r;
col[sz]=c;
S[c]++;
sz++;
}
R[sz-1]=first;
L[first]=sz-1;
}
#define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])
void remove (int c)
{
L[R[c]]=L[c];
R[L[c]]=R[c];
FOR(i,D,c)
FOR(j,R,i)
{
U[D[j]]=U[j];
D[U[j]]=D[j];
--S[col[j]];
}
}
void restore(int c)
{
FOR(i,U,c)
FOR(j,L,i)
{
++S[col[j]];
U[D[j]]=j;
D[U[j]]=j;
}
L[R[c]]=c;
R[L[c]]=c;
}
bool dfs(int d)
{
if(R[0]==0)
{
ansd=d;
return true;
}
int c=R[0];
FOR(i,R,0)if(S[i]<S[c])c=i;
remove(c);
FOR(i,D,c)
{
ans[d]=row[i];
FOR(j,R,i)remove(col[j]);
if(dfs(d+1))return true;
FOR(j,L,i)restore(col[j]);
}
restore(c);
return false;
}
bool solve(vector <int>& v)
{
v.clear();
if(!dfs(0))return false;
for(int i=0; i<ansd; ++i)v.push_back(ans[i]);
return true;
}
};
DLX slover;
const int SLOT=0;
const int ROW=1;
const int COL=2;
const int SUB=3;
int encode(int a,int b,int c)
{
return a*16*16+b*16+c+1;
}
void decode(int code,int& a,int& b,int& c)
{
code--;
c=code%16;
code/=16;
b=code%16;
code/=16;
a=code;
}
int puzzle[20][20];
int main()
{
//freopen("data1.in","r",stdin);
//freopen("data1.out","w",stdout);
for(int i=0; i<16; ++i)
{
for(int j=0; j<16; ++j)
{
scanf("%d",&puzzle[i][j]);
}
}
slover.init(16*16*4);
for(int r=0; r<16; ++r)
{
for(int c=0; c<16; ++c)
{
for(int v=0; v<16; ++v)
{
if(puzzle[r][c]==0||puzzle[r][c]==v+1)
{
vector <int> coulumns;
coulumns.push_back(encode(SLOT,r,c));
coulumns.push_back(encode(ROW,r,v));
coulumns.push_back(encode(COL,c,v));
coulumns.push_back(encode(SUB,r/4*4+c/4,v));
slover.addRow(encode(r,c,v),coulumns);
}
}
}
}
vector <int> ans;
slover.solve(ans);
for(int i=0; i<ans.size(); ++i)
{
int r,c,v;
decode(ans[i],r,c,v);
puzzle[r][c]=v+1;
}
for(int i=0; i<16; ++i)
{
for(int j=0; j<16; ++j)
{
if(j)putchar(' ');
printf("%d",puzzle[i][j]);
}
puts("");
}
return 0;
}
E、简单的GCD
这一题是数论的题目,可以欧拉+容斥+搞搞搞=AC,其实最好的方法是利用莫比乌斯反演的结论(可以百度),其实简单来说就是,关键是求这个函数的值,求出来后容斥答案就出来了。
代码:
<span style="font-size:18px;">#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <climits>
#include <utility>
using namespace std;
const int MAXN = 1000000;
int b,d,k;
long long ans,cnt;
bool vis[MAXN+5];
int prime[MAXN+5],mu[MAXN+5];
void init()
{
memset(vis,false,sizeof(vis));
mu[1]=1;
int tot=0;
for(int i=2; i<=MAXN; i++)
{
if(!vis[i])
{
prime[tot++]=i;
mu[i]=-1;
}
for(int j=0; j<tot; j++)
{
if(i*prime[j]>MAXN) break;
vis[i*prime[j]]=true;
if( i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
else
{
mu[i*prime[j]]=-mu[i];
}
}
}
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
int T,cas=1;
init();
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&b,&d,&k);
b/=k;
d/=k;
if(b>d)swap(b,d);
ans=0;
cnt=0;
for(int i=1; i<=b; ++i)
{
ans+=(long long)mu[i]*(b/i)*(d/i);
cnt+=(long long)mu[i]*(b/i)*(b/i);
}
ans-=cnt/2;
printf("Case %d: %lld\n",cas++,ans);
}
return 0;
}</span>