1. 程式人生 > >【NOIP2010】提高組

【NOIP2010】提高組

print 要求 pan 日常 jos 拓展 h+ org class

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

【NOIP2010】提高組