这天考的是NOIP2010年的复赛题。最后一道搜索题简直恶心……(最后还是借助网上代码的力量A掉的)搜索简直太考验耐心了。。
第二道似乎可以用dp来做,但当时考试的时候想的就是st表(然而并没有编出来,我大概是不会写st表了吧)这样编还是挺简单的……
选择客栈
//我大概是没学过st表
//求内存别爆啊
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200010
#define M 100010
#define ms(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,k,p,ans=0;
int q,w[N],color[M][55],cnt[55];
int st[N][20],logn[N];
void ST(){
logn[1]=0;
for(register int i=2;i<=n;i++)
logn[i]=logn[i>>1]+1;
for(register int j=1;j<=n;j++) st[j][0]=w[j];
for(int j=1;(1<<j)<=n;j++){
for(register int i=1;i+(1<<j)-1<=n;i++)
st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
}
int query(int l,int r){
int len=r-l+1;
int k=logn[len];
return min(st[l][k],st[r-(1<<k)+1][k]);
}
int main(){
freopen("hotel.in","r",stdin);
freopen("hotel.out","w",stdout);
ms(cnt,0);ms(color,0);
scanf("%d%d%d",&n,&k,&p);
for(register int i=1;i<=n;i++){
int x;
scanf("%d%d",&x,&w[i]);
color[++cnt[x]][x]=i;
}
ST();
for(register int i=0;i<k;i++){//k kinds
for(register int j=1;j<=cnt[i];j++){//the number
for(register int d=j+1;d<=cnt[i];d++){
int u=color[j][i],v=color[d][i];
if(query(u,v)<=p){
// printf("%d %d\n",u,v);
// printf("%d ",d);
ans+=cnt[i]-d+1;break;
}
}
}
}
printf("%d",ans);
return 0;
}
Mayan游戏
//不想说话
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ms(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,c=-1;
int a[15][15],ans[16][17],cnt[16];
bool f[17][17];
void print(){
for(int i=1;i<=n;i++){
printf("%d %d %d\n",ans[i][0],ans[i][1],ans[i][2]);
}
exit(0);
}//alright
void fall(int x){
for(int i=0;i<7;i++){
if(a[x][i]==0){
int j=i+1;
while(j<7&&a[x][j]==0) j++;
if(j==7) return ;
else swap(a[x][i],a[x][j]);
}
}
}//alright
int counter(){
int mmin=10000;
for(int i=1;i<=c;i++){
if(cnt[i]!=0&&cnt[i]<mmin) mmin=cnt[i];
}
if(mmin==10000) mmin=0;
return mmin;
}
bool clear(){
bool flag = false;
for(int i=0;i<5;i++){
for(int j=0;j<7;j++){
if(!a[i][j]) continue;
if(i<3&&a[i][j]==a[i+1][j]&&a[i+1][j]==a[i+2][j]){
f[i][j]=true;
f[i+1][j]=true;
f[i+2][j]=true;
}
if(j<5&&a[i][j]==a[i][j+1]&&a[i][j+1]==a[i][j+2]){
f[i][j]=true;
f[i][j+1]=true;
f[i][j+2]=true;
}
}
}
for(int i=0;i<5;i++)
for(int j=0;a[i][j]&&j<7;j++)
if(f[i][j]){
flag = true;
cnt[a[i][j]]--;
a[i][j]=0;
f[i][j]=0;
}
for(int i=0;i<5;i++)
fall(i);
return flag;
}
void dfs(int d){
int b[17][17],bcnt[17];
for(int i=0;i<5;i++)
for(int j=0;j<7;j++)
b[i][j]=a[i][j];
for(int i=1;i<=c;i++)
bcnt[i]=cnt[i];
for(int i=0;i<5;i++)
for(int j=0;a[i][j]&&j<7;j++)
for(int k=1;k>=-1;k-=2)
if(i+k>=0&&i+k<5){
if((k==-1&&a[i-1][j])||a[i+k][j]==a[i][j]) continue;
ans[d][0]=i;ans[d][1]=j;ans[d][2]=k;
swap(a[i+k][j],a[i][j]);
fall(i);fall(i+k);
while(clear());
int tmp=counter();
if(d==n){
if(tmp==0) print();
}//一定要有括号!!!否则下面一个else就与这个if凑一起了
else if(tmp>2) dfs(d+1);
for(int i=0;i<5;i++)
for(int j=0;j<7;j++)
a[i][j]=b[i][j];
for(int i=1;i<=c;i++)
cnt[i]=bcnt[i];
}
}
int main(){
ms(a,0);ms(f,0);ms(cnt,0);ms(ans,0);
scanf("%d",&n);
for(int i=0;i<5;i++){
int cunt=0,x=1;
while(x!=0){
scanf("%d",&x);
if(x==0) break;
a[i][cunt]=x;
cunt++;
c=max(c,x);
cnt[x]++;
}
}
/* for(int i=0;i<5;i++){
for(int j=0;j<7;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}*/
dfs(1);
printf("-1");
return 0;
}
仿佛没学过数据结构的我……
后悔当时怎么没有写博客,现在都不知道去哪抄程序.jpg