A. 【NOIP 2010 提高组】机器翻译
#include<bits/stdc++.h>
using namespace std;
int m,n,a[1010],cnt,tot;
bool b[1010];
queue<int>q;
int main(){
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(!b[a[i]]){
q.push(a[i]);
b[a[i]]=1;
cnt++;
tot++;
if(tot>m)b[q.front()]=0,q.pop();
}
}
printf("%d",cnt);
return 0;
}
题解:第一题用队列,先读入就入队满了就出队。
B. 【NOIP 2010 提高组】乌龟棋
#include<bits/stdc++.h>
using namespace std;
int n,m,a[400],b[200],tmp,f[41][41][41][41],s;
bool book[400];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
scanf("%d",&tmp),b[tmp]++;
f[0][0][0][0]=a[1];
for(int i=0;i<=b[4];i++)
for(int j=0;j<=b[3];j++)
for(int k=0;k<=b[2];k++)
for(int l=0;l<=b[1];l++){
s=i*4+j*3+k*2+l+1;
if(i>0)f[i][j][k][l]=max(f[i][j][k][l],f[i-1][j][k][l]+a[s]);
if(j>0)f[i][j][k][l]=max(f[i][j][k][l],f[i][j-1][k][l]+a[s]);
if(k>0)f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k-1][l]+a[s]);
if(l>0)f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k][l-1]+a[s]);
}
printf("%d",f[b[4]][b[3]][b[2]][b[1]]);
return 0;
}
题解:思维数组f[i][j][k][l]分别代表用几张第1 2 3 4张时得到的最大分数。
C. 【NOIP 2010 提高组】关押罪犯
#include<bits/stdc++.h>
using namespace std;
struct node{int x,y,w;}e[100010];
int n,m,up[20010],b[20010];
bool comp(node a,node b){return a.w>b.w;}
int find(int x){return x==up[x]?x:find(up[x]);}
void join(int x,int y){up[find(x)]=find(y);}
bool check(int x,int y){return find(x)==find(y);}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)up[i]=i;
for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
sort(e+1,e+m+1,comp);
for(int i=1;i<=m+1;i++){
if(check(e[i].x,e[i].y)){
printf("%d",e[i].w);
return 0;
}
if(!b[e[i].x])b[e[i].x]=e[i].y;
else join(b[e[i].x],e[i].y);
if(!b[e[i].y])b[e[i].y]=e[i].x;
else join(b[e[i].y],e[i].x);
}
return 0;
}
题解:用并查集,先按仇恨程度从大到小排序,然后用b[x]=y将敌人标记,如果b[x]!=0,说明有敌人了,就将敌人的敌人合并。
D. 【NOIP 2010 提高组】引水入城
#include<bits/stdc++.h>
using namespace std;
int n,m,g[510][510],ans,r[510][510],l[510][510];
bool b[510][510],flag;
void dfs(int x,int y){
int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}},tx,ty;
b[x][y]=1;
for(int i=0;i<4;i++){
tx=d[i][0]+x;
ty=d[i][1]+y;
if(tx<1||ty<1||tx>n||ty>m)continue;
if(g[tx][ty]>=g[x][y])continue;
if(!b[tx][ty])dfs(tx,ty);
l[x][y]=min(l[x][y],l[tx][ty]);
r[x][y]=max(r[x][y],r[tx][ty]);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&g[i][j]);
memset(l,0x3f,sizeof(l));
memset(r,0,sizeof(r));
for(int i=1;i<=m;i++)
l[n][i]=r[n][i]=i;
for(int i=1;i<=m;i++)
if(!b[1][i])dfs(1,i);
for(int i=1;i<=m;i++)
if (!b[n][i])flag=1,ans++;
if(flag){printf("0\n%d",ans);return 0;}
int left=1;
while(left<=m){
int maxr=0;
for(int i=1;i<=m;i++)
if(l[1][i]<=left)
maxr=max(maxr,r[1][i]);
ans++;
left=maxr+1;
}
printf("1\n%d",ans);
return 0;
}
题解:dfs靠近河的一边,如果没有路能到达沙漠,输出0。若能到达,就用贪心用区间覆盖[1,j]的最少区间数就是答案。