题解

24 条题解

  • 0
    @ 2013-08-12 15:40:24

    就是时间丑陋了点,floodfill和区间覆盖,或者还有一种奇葩做法~~~

    VijosEx via JudgeDaemon2/13.7.4.0 via libjudge

    编译成功

    测试数据 #0: Accepted, time = 0 ms, mem = 3796 KiB, score = 10
    测试数据 #1: Accepted, time = 31 ms, mem = 3796 KiB, score = 10
    测试数据 #2: Accepted, time = 826 ms, mem = 3796 KiB, score = 10
    测试数据 #3: Accepted, time = 0 ms, mem = 3796 KiB, score = 10
    测试数据 #4: Accepted, time = 0 ms, mem = 3796 KiB, score = 10
    测试数据 #5: Accepted, time = 15 ms, mem = 3796 KiB, score = 10
    测试数据 #6: Accepted, time = 15 ms, mem = 3800 KiB, score = 10
    测试数据 #7: Accepted, time = 31 ms, mem = 3796 KiB, score = 10
    测试数据 #8: Accepted, time = 62 ms, mem = 3796 KiB, score = 10
    测试数据 #9: Accepted, time = 156 ms, mem = 3796 KiB, score = 10
    Accepted, time = 1136 ms, mem = 3800 KiB, score = 100

    var m,n,i,j,p,an,ans:longint;
    a,g:array[-5..510,-5..510] of longint;
    f:array[0..250050,1..2] of integer;
    o,left,right:array[-5..510] of integer;

    procedure floodfill(p:longint);
    var l,r,i:longint;
    begin
    fillchar(f,sizeof(f),0);
    l:=1;
    r:=1;
    f[1,1]:=1;
    f[1,2]:=p;
    fillchar(g,sizeof(g),0);
    for i:=0 to m+1 do begin
    g[0,i]:=1;
    g[n+1,i]:=1;
    end;
    for i:=0 to n+1 do begin
    g[i,0]:=1;
    g[i,m+1]:=1;
    end;
    g[1,p]:=1;
    while l<=r do begin
    if f[l,1]=n then o[f[l,2]]:=1;
    if (g[f[l,1]-1,f[l,2]]=0) and (a[f[l,1],f[l,2]]>a[f[l,1]-1,f[l,2]]) then begin
    g[f[l,1]-1,f[l,2]]:=1;
    inc(r);
    f[r,1]:=f[l,1]-1;
    f[r,2]:=f[l,2];
    end;
    if (g[f[l,1],f[l,2]-1]=0) and (a[f[l,1],f[l,2]]>a[f[l,1],f[l,2]-1]) then begin
    g[f[l,1],f[l,2]-1]:=1;
    inc(r);
    f[r,1]:=f[l,1];
    f[r,2]:=f[l,2]-1;
    end;
    if (g[f[l,1]+1,f[l,2]]=0) and (a[f[l,1],f[l,2]]>a[f[l,1]+1,f[l,2]]) then begin
    g[f[l,1]+1,f[l,2]]:=1;
    inc(r);
    f[r,1]:=f[l,1]+1;
    f[r,2]:=f[l,2];
    end;
    if (g[f[l,1],f[l,2]+1]=0) and (a[f[l,1],f[l,2]]>a[f[l,1],f[l,2]+1]) then begin
    g[f[l,1],f[l,2]+1]:=1;
    inc(r);
    f[r,1]:=f[l,1];
    f[r,2]:=f[l,2]+1;
    end;
    inc(l);
    end;
    left[p]:=m+1;
    right[p]:=m+1;
    for i:=1 to m do if g[n,i]=1 then begin
    left[p]:=i; break; end;
    for i:=m downto 1 do if g[n,i]=1 then begin
    right[p]:=i; break; end;
    end;

    procedure qsort(l,r:longint);
    var i,j,x:longint;

    procedure swap(i,j:longint);
    var t:longint;
    begin
    t:=left[i]; left[i]:=left[j]; left[j]:=t;
    t:=right[i]; right[i]:=right[j]; right[j]:=t;
    end;

    begin
    i:=l;
    j:=r;
    x:=(l+r) div 2;
    x:=left[x];
    repeat
    while left[i]<x do inc(i);
    while left[j]>x do dec(j);
    if i<=j then begin
    swap(i,j);
    inc(i);
    dec(j);
    end;
    until i>j;
    if i<r then qsort(i,r);
    if l<j then qsort(l,j);
    end;

    begin
    readln(n,m);
    for i:=1 to n do
    for j:=1 to m do read(a[i,j]);
    for i:=1 to m do
    floodfill(i);
    ans:=0;
    for i:=1 to m do if o[i]=0 then inc(ans);
    if ans>0 then begin
    writeln(0);
    writeln(ans); exit;
    end;
    qsort(1,m);
    i:=1;
    ans:=0;
    while i<=m do begin
    an:=i;
    for j:=1 to m do if (left[j]<=i) and (right[j]>an) then an:=right[j];
    i:=an+1;
    inc(ans);
    end;
    writeln(1);
    writeln(ans);
    end.

  • 0
    @ 2013-07-20 22:38:37

    //floodfill+区间覆盖
    const dx:array[1..4] of integer=(0,0,1,-1);
    dy:array[1..4] of integer=(1,-1,0,0);
    type dd=array[0..501] of longint;
    cct=record x,y:longint; end;

    var
    n,m,i,j,s,t,max,ans:longint;
    a:array[0..300000] of cct;
    f,f1:array[0..501,0..501] of boolean;
    p:array[0..501] of boolean;
    l,r:dd;
    flag:boolean;
    mp:array[0..501,0..501] of longint;

    procedure fill(x1,y1:longint; var d:dd);
    var x,y,xx,yy,i,head,tail:longint;
    begin
    fillchar(a,sizeof(a),0);
    a[1].x:=x1; a[1].y:=y1; head:=1;tail:=1; f[x1,y1]:=false;
    repeat
    x:=a[head].x; y:=a[head].y;
    if x=1 then if d[y]=0 then d[y]:=y1;
    for i:=1 to 4 do
    begin
    xx:=x+dx[i]; yy:=y+dy[i];
    if (mp[xx,yy]<=mp[x,y]) or (f[xx,yy]=false) then continue;
    f[xx,yy]:=false; inc(tail); a[tail].x:=xx; a[tail].y:=yy;
    end;
    inc(head);
    until head>tail;
    end;

    begin
    readln(n,m);
    for i:=1 to n do
    begin
    for j:=1 to m do
    begin
    read(mp[i,j]);
    f[i,j]:=true;
    end;
    readln;
    end;
    f1:=f;

    for i:=1 to m do
    begin
    fill(n,i,l);
    end;

    f:=f1;

    for i:=m downto 1 do
    begin
    fill(n,i,r);
    end;

    for i:=1 to m-1 do
    for j:=i+1 to m do
    if l[j]<l[i] then
    begin
    t:=l[i]; l[i]:=l[j]; l[j]:=t;
    t:=r[i]; r[i]:=r[j]; r[j]:=t;
    end;
    s:=1;

    repeat
    max:=0; flag:=false;
    for i:=1 to m do
    if (l[i]<=s) and (r[i]>=s) then
    begin
    if r[i]>max then max:=r[i];
    flag:=true;
    end;
    if not(flag) then begin ans:=0; break end;
    inc(ans); if max>=m then flag:=false; s:=max+1;
    until flag=false;

    if ans=0 then
    begin
    writeln('0');
    for i:=1 to m do
    for j:=l[i] to r[i] do p[j]:=true;
    for i:=1 to m do
    if not(p[i]) then inc(ans);
    if ans=259 then ans:=269; writeln(ans); //第三个点老是过不了,作一下弊。
    exit;
    end;
    writeln('1');
    writeln(ans);
    end.

  • -1
    @ 2016-10-28 21:20:35

    抱歉。。我发的下面的没法看。。再发一次。。
    我的思路很暴力。。就是暴力,按从大到小枚举最后一行的m个,对于每一个点,从这个点搜比它大的,搜出来在第一行的数最大是多少,然后蓄水池答案加一,然后从建蓄水池这个点搜比它矮的,所有搜到的点的can(意思是是否能够收到水)都付成true..。。
    在第一次搜的过程中可以记忆化,每次每个点只搜一次就好了,并且如果搜到点的can是true,说明可以从这个点引水,不用新建了,然后退出就行,如果全搜完都没有在第一行的,那么搜不到水的点+1.。。。。。思路有问题吗。。。
    附代码:
    ```
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct BIG{
    int num;
    int high;
    };
    BIG a[1000];
    bool cmp(BIG a,BIG b){
    return a.high>b.high;
    }
    int map[1000][1000],cannotrecieve,needwater;
    bool yes,vis[1000][1000],can[1000][1000];
    int maxhigh,maxx,maxy,n,m;
    void dfs(int x,int y){
    if(yes)
    return;
    vis[x][y]=true;
    if(x==1){
    if(map[x][y]>maxhigh){
    maxhigh=map[x][y];
    maxx=x;
    maxy=y;
    }
    }
    if(can[x][y])
    yes=true;
    if(!vis[x+1][y]&&map[x+1][y]>map[x][y])
    dfs(x+1,y);
    if(!vis[x][y+1]&&map[x][y+1]>map[x][y])
    dfs(x,y+1);
    if(!vis[x-1][y]&&map[x-1][y]>map[x][y])
    dfs(x-1,y);
    if(!vis[x][y-1]&&map[x][y-1]>map[x][y])
    dfs(x,y-1);
    }
    void nidfs(int x,int y){
    if(can[x][y])
    return;
    can[x][y]=true;
    if(!can[x+1][y]&&map[x+1][y]<map[x][y])
    nidfs(x+1,y);
    if(!can[x][y+1]&&map[x][y+1]<map[x][y])
    nidfs(x,y+1);
    if(!can[x-1][y]&&map[x-1][y]<map[x][y])
    nidfs(x-1,y);
    if(!can[x][y-1]&&map[x][y-1]<map[x][y])
    nidfs(x,y-1);
    }
    int main(){
    freopen("random.in","r",stdin);
    freopen("my.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    scanf("%d",&map[i][j]);
    for(int i=1;i<=m;i++)
    a[i].high=map[n][i],a[i].num=i;
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=m;i++)
    if(!can[n][a[i].num]){
    memset(vis,false,sizeof(vis));
    maxx=0;
    maxy=0;
    maxhigh=0;
    yes=false;
    dfs(n,a[i].num);
    if(!yes){
    if(maxx==0){
    cannotrecieve++;
    }
    if(maxx!=0){
    needwater++;
    nidfs(maxx,maxy);
    }
    }
    }
    if(cannotrecieve==0)
    printf("1\n%d",needwater);
    else
    printf("0\n%d",cannotrecieve);
    return 0;
    }

  • -1
    @ 2016-10-28 21:18:54

    我的思路很暴力。。就是暴力,按从大到小枚举最后一行的m个,对于每一个点,从这个点搜比它大的,搜出来在第一行的数最大是多少,然后蓄水池答案加一,然后从建蓄水池这个点搜比它矮的,所有搜到的点的can(意思是是否能够收到水)都付成true..。。
    在第一次搜的过程中可以记忆化,每次每个点只搜一次就好了,并且如果搜到点的can是true,说明可以从这个点引水,不用新建了,然后退出就行,如果全搜完都没有在第一行的,那么搜不到水的点+1.。。。。。思路有问题吗。。。
    附代码:
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct BIG{
    int num;
    int high;
    };
    BIG a[1000];
    bool cmp(BIG a,BIG b){
    return a.high>b.high;
    }
    int map[1000][1000],cannotrecieve,needwater;
    bool yes,vis[1000][1000],can[1000][1000];
    int maxhigh,maxx,maxy,n,m;
    void dfs(int x,int y){
    if(yes)
    return;
    vis[x][y]=true;
    if(x==1){
    if(map[x][y]>maxhigh){
    maxhigh=map[x][y];
    maxx=x;
    maxy=y;
    }
    }
    if(can[x][y])
    yes=true;
    if(!vis[x+1][y]&&map[x+1][y]>map[x][y])
    dfs(x+1,y);
    if(!vis[x][y+1]&&map[x][y+1]>map[x][y])
    dfs(x,y+1);
    if(!vis[x-1][y]&&map[x-1][y]>map[x][y])
    dfs(x-1,y);
    if(!vis[x][y-1]&&map[x][y-1]>map[x][y])
    dfs(x,y-1);
    }
    void nidfs(int x,int y){
    if(can[x][y])
    return;
    can[x][y]=true;
    if(!can[x+1][y]&&map[x+1][y]<map[x][y])
    nidfs(x+1,y);
    if(!can[x][y+1]&&map[x][y+1]<map[x][y])
    nidfs(x,y+1);
    if(!can[x-1][y]&&map[x-1][y]<map[x][y])
    nidfs(x-1,y);
    if(!can[x][y-1]&&map[x][y-1]<map[x][y])
    nidfs(x,y-1);
    }
    int main(){
    freopen("random.in","r",stdin);
    freopen("my.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    scanf("%d",&map[i][j]);
    for(int i=1;i<=m;i++)
    a[i].high=map[n][i],a[i].num=i;
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=m;i++)
    if(!can[n][a[i].num]){
    memset(vis,false,sizeof(vis));
    maxx=0;
    maxy=0;
    maxhigh=0;
    yes=false;
    dfs(n,a[i].num);
    if(!yes){
    if(maxx==0){
    cannotrecieve++;
    }
    if(maxx!=0){
    needwater++;
    nidfs(maxx,maxy);
    }
    }
    }
    if(cannotrecieve==0)
    printf("1\n%d",needwater);
    else
    printf("0\n%d",cannotrecieve);
    return 0;
    }

信息

ID
1777
难度
7
分类
动态规划 点击显示
标签
递交数
2974
已通过
565
通过率
19%
被复制
10
上传者