【NOIP2010】提高组

T1机器翻译

题目链接

直接上队列的模拟题,日常没题解。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 int m,n;
 5 int read(){
 6     int ans=0,f=1;char c=getchar();
 7     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
 8     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
 9     return ans*f;
10 }
11 int q[1005],h=1,t=0;
12 bool ok[1005];
13 int main(){
14     m=read();n=read();
15     int sum=0;
16     for(int i=1,a;i<=n;i++){
17         a=read();
18         if(ok[a])continue;
19         sum++;if(!m)continue;
20         q[++t]=a;ok[a]=1;
21         if(t-h+1>m)ok[q[h]]=0,h++;
22     }
23     printf("%d",sum);
24     return 0;
25 }
T1

T2乌龟棋

题目链接

f[i][j][k][p]表示四种卡片分别用了i、j、k.、p张,然后n4转移就没了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 int read(){
 5     int ans=0,f=1;char c=getchar();
 6     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
 7     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
 8     return ans*f;
 9 }
10 int max(int x,int y){return x>y?x:y;}
11 int f[45][45][45][45];
12 int a[355],count[5];
13 int main(){
14     int n=read(),m=read();
15     for(int i=1;i<=n;i++)a[i]=read();
16     for(int i=1,b;i<=m;i++)b=read(),count[b]++;
17     for(int i=0;i<=count[1];i++){
18         for(int j=0;j<=count[2];j++){
19             for(int k=0;k<=count[3];k++){
20                 for(int p=0;p<=count[4];p++){
21                     int now=i+j*2+k*3+p*4+1;
22                     int p1=0,p2=0,p3=0,p4=0;
23                     if(i)p1=f[i-1][j][k][p];
24                     if(j)p2=f[i][j-1][k][p];
25                     if(k)p3=f[i][j][k-1][p];
26                     if(p)p4=f[i][j][k][p-1];
27                     f[i][j][k][p]=max(max(p1,p2),max(p3,p4))+a[now];
28                 }
29             }
30         }
31     }
32     printf("%d",f[count[1]][count[2]][count[3]][count[4]]);
33     return 0;
34 }
T2

T3关押罪犯

题目链接

后来成为并查集的经典题,i和i+n表示对立的两个集合。

将冲突关系按怒气值从大到小排个序。

每次尝试把两名罪犯放到不同的两个集合里,发现已经在同一个集合里就可以直接输出答案了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 const int N=2e4+10,M=1e5+10;
 5 int fa[N*2];
 6 int n,m;
 7 struct node{
 8     int fr,to,w;
 9     bool operator <(const node&p)const {return p.w<w;}
10 }e[M];
11 int getf(int x){return x==fa[x]?x:fa[x]=getf(fa[x]);}
12 int read(){
13     int ans=0,f=1;char c=getchar();
14     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
15     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
16     return ans*f;
17 }
18 int main(){
19     n=read();m=read();
20     for(int i=1;i<=n;i++)fa[i]=i,fa[i+n]=i+n;
21     for(int i=1,a,b,c;i<=m;i++){
22         a=read();b=read();c=read();
23         e[i]=(node){a,b,c};
24     }
25     std::sort(e+1,e+1+m);
26     for(int i=1;i<=m;i++){
27         int p1=e[i].fr,p2=e[i].to,w=e[i].w;
28         int f1=getf(p1),f2=getf(p2);
29         if(f1==f2)return printf("%d",w),0;
30         int fa1=getf(p1+n),fa2=getf(p2+n);
31         fa[f1]=fa2;fa[f2]=fa1;
32     }
33     printf("0");
34     return 0;
35 }
T3

T4引水入城

题目链接

灌水法,先从顶端dfs染色,扫一遍最下一层,如果有点没被染色就说明不能满足要求。

然后从下往上反灌水,因为顶层的点所覆盖的底层的点必然是连续的一段(反证法),因此就变成了去最少的线段覆盖给定的区间问题。

按左端点排个序然后不断往后贪心拓展就好了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define mem(a,p) memset(a,p,sizeof(a))
 5 const int N=505;
 6 using std::sort;
 7 using std::max;
 8 struct node{int li,ri;}e[N];
 9 int n,m,tot=0,mp[N][N],cc[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
10 int read(){
11     int ans=0,f=1;char c=getchar();
12     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
13     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
14     return ans*f;
15 }
16 int f[N][N],li[N][N],ri[N][N];
17 int xx[4]={1,-1,0,0},yy[4]={0,0,1,-1};
18 int qx[250005],qy[250005];
19 bool cmp(node a,node b){return a.li<b.li;}
20 void dfs(int x,int y){
21     for(int i=0;i<4;i++){
22         int px=x+cc[i][0],py=y+cc[i][1];
23         if(px<1||px>n||py>m||py<1||f[px][py]||mp[px][py]>=mp[x][y])continue;
24         f[px][py]=f[x][y];
25         dfs(px,py);
26     }
27 }
28 void dfs1(int x,int y){
29     for(int i=0;i<4;i++){
30         int px=x+cc[i][0],py=y+cc[i][1];
31         if(px<1||px>n||py<1||py>m||mp[px][py]<=mp[x][y])continue;
32         bool flag=0;
33         if(li[px][py]>li[x][y])li[px][py]=li[x][y],flag=1;
34         if(ri[px][py]<ri[x][y])ri[px][py]=ri[x][y],flag=1;
35         if(flag)dfs1(px,py);
36     }
37 }
38 int main(){
39     n=read();m=read();
40     for(int i=1;i<=n;i++)
41         for(int j=1;j<=m;j++)
42         mp[i][j]=read();
43     for(int i=1;i<=m;i++)f[1][i]=1;
44     for(int i=1;i<=m;i++)dfs(1,i);
45     int sum=0;bool flag=0;
46     for(int i=1;i<=m;i++)if(!f[n][i])flag=1,sum++;
47     if(flag)return printf("0\n%d",sum),0;
48     mem(li,127);
49     for(int i=1;i<=m;i++)li[n][i]=ri[n][i]=i;
50     for(int i=1;i<=m;i++)dfs1(n,i);
51     for(int i=1;i<=m;i++)
52         if(li[1][i]!=li[0][0])
53             e[++tot]=(node){li[1][i],ri[1][i]};
54     sort(e+1,e+1+tot,cmp);
55     int now=0,to=0;
56     for(int i=1;i<=tot;i++){
57         if(now+1>=e[i].li)to=max(to,e[i].ri);
58         else now=to,to=max(to,e[i].ri),sum++;
59     }
60     if(now!=to)sum++;
61     printf("1\n%d",sum);
62     return 0;
63 }
T4

 

posted @ 2017-11-05 20:45  Child-Single  阅读(273)  评论(0编辑  收藏  举报