24 条题解
-
2ATHENS_ LV 9 @ 2017-10-13 23:11:19
先bfs,注意一个储水厂可到达的沙漠地区肯定是连续的,之后做区间覆盖就好了。
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <queue> using namespace std; const int maxn=505; int dx[]={1,-1,0,0}; int dy[]={0,0,-1,1}; int n,m,h[maxn][maxn],ans; bool vis[maxn],vist[maxn][maxn]; struct node{ int l,r; }e[maxn]; struct odd{ int x,y; }; queue <odd> q; bool cmp(const node &a,const node &b){ if(a.l<b.l)return 1; else if(a.l==b.l)return a.r<b.r; return 0; } void bfs(int x){ memset(vist,0,sizeof vist); odd st; st.x=1;st.y=x; q.push(st);vist[1][x]=1; while(!q.empty()){ odd u=q.front();q.pop(); if(u.x==n){ vis[u.y]=1; if(e[x].r<u.y)e[x].r=u.y; if(!e[x].l)e[x].l=u.y,e[x].r=u.y; else if(e[x].l>u.y)e[x].l=u.y; } for(register int i=0;i<4;++i){ int nx=u.x+dx[i]; int ny=u.y+dy[i]; if(nx<1||nx>n||ny<1||ny>m||h[nx][ny]>=h[u.x][u.y]||vist[nx][ny])continue; odd neww; neww.x=nx,neww.y=ny;q.push(neww);vist[nx][ny]=1; } } } int main(){ scanf("%d%d",&n,&m); for(register int i=1;i<=n;++i){ for(register int j=1;j<=m;++j){ scanf("%d",&h[i][j]); } } for(register int i=1;i<=m;++i){ bfs(i); } bool flag=0;int ct=0; for(register int i=1;i<=m;++i){ if(!vis[i])++ct,flag=1; } if(flag){ printf("0\n%d",ct); return 0; } sort(e+1,e+m+1,cmp); int idx=1,s=1,t,cnt=0; while(s<=m){ t=s; for(register int i=idx;i<=m;++i){ if(e[i].l<=t){ if(e[i].r>=t)s=e[i].r; } else { idx=i;break; } } cnt++;s++; } printf("1\n%d",cnt); return 0; }
-
02019-06-30 17:02:45@
#include<bits/stdc++.h> using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) #define REP(i,a,b) for(int i = a; i <= b; ++i) #define PER(i,a,b) for(int i = a; i >= b; --i) #define PB push_back #define MP make_pair #define fi first #define se second typedef long long LL; typedef double DB; const int maxn = 500; int n, m; int seg[maxn*maxn+5]; int hi[maxn+5][maxn+5]; int L[maxn+5][maxn+5], R[maxn+5][maxn+5]; struct Node { int l, r, id; Node() {} Node(int _l, int _r, int _id) : l(_l), r(_r), id(_id) {} bool operator<(const Node &a) { return l < a.l; } } fk[maxn+5]; void Min(int &a, int b) { a = min(a,b); } void Max(int &a, int b) { a = max(a,b); } const int walk[4][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}}; bool vi[maxn+5][maxn+5]; int bfs(int top) { queue<int> q; REP(i,1,top) q.push(1000 + seg[i]), vi[1][seg[i]] = 1; while(!q.empty()) { int x = q.front()/1000, y = q.front()%1000; q.pop(); for(int t = 0; t < 4; ++t) { int xx = x + walk[t][0]; int yy = y + walk[t][1]; if(xx<1 || xx>n || yy<1 || yy>m) continue; if(vi[xx][yy] || hi[xx][yy]>=hi[x][y]) continue; vi[xx][yy] = 1; q.push(xx*1000 + yy); } } int res = 0; REP(i,1,m) res += (vi[n][i]==0); return res; } int main() { scanf("%d%d", &n, &m); int top = 0; REP(i,1,n) REP(k,1,m) { scanf("%d", &hi[i][k]); seg[++top] = i*1000 + k; } sort(seg+1, seg+1+top, [&](int a, int b) { return hi[a/1000][a%1000]<hi[b/1000][b%1000]; } ); REP(i,1,top) { int x = seg[i]/1000, y = seg[i]%1000; if(x==n) L[x][y] = R[x][y] = y; else L[x][y] = m+10, R[x][y] = -1; for(int t = 0; t < 4; ++t) { int xx = x + walk[t][0]; int yy = y + walk[t][1]; if(xx<1 || xx>n || yy<1 || yy>m || hi[xx][yy]>=hi[x][y]) continue; Min(L[x][y], L[xx][yy]); Max(R[x][y], R[xx][yy]); } } REP(i,1,m) fk[i] = Node(L[1][i], R[1][i], i); sort(fk+1, fk+1+m); int pt = 1, now = 0; top = 0; priority_queue<pair<int,int>> q; while(now<m) { while(pt<=m && fk[pt].l<=now+1) { q.push( pair<int,int>(fk[pt].r, fk[pt].id) ); ++pt; } if(q.empty() || q.top().fi<=now) break; now = q.top().fi; seg[++top] = q.top().se; q.pop(); } if(now<m) { top = 0; REP(i,1,m) seg[++top] = i; } int cnt = bfs(top); if(cnt) printf("0\n%d\n", cnt); else printf("1\n%d\n", top); return 0; }
-
02017-10-13 23:09:03@
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; const int LIM=503; struct Stage{ int l,r; Stage():l(INF),r(-INF){} inline bool operator < (Stage r) const { return l<r.l; } }S[LIM]; int n,m,M[LIM][LIM],f[LIM],cnt=0; bool vis[LIM][LIM],ans[LIM]; void dfs(int x,int y,int ori) { vis[x][y]=1; if(x==m){ ans[y]=1; S[ori].l=min(S[ori].l,y); S[ori].r=max(S[ori].r,y); } if(M[x+1][y]<M[x][y]&&x!=m&&!vis[x+1][y]) dfs(x+1,y,ori); if(M[x-1][y]<M[x][y]&&x!=1&&!vis[x-1][y]) dfs(x-1,y,ori); if(M[x][y+1]<M[x][y]&&y!=n&&!vis[x][y+1]) dfs(x,y+1,ori); if(M[x][y-1]<M[x][y]&&y!=1&&!vis[x][y-1]) dfs(x,y-1,ori); } int main() { scanf("%d%d",&m,&n); memset(f,63,sizeof f); f[0]=0; for(int i=1;i<=m;++i) for(int j=1;j<=n;++j) scanf("%d",&M[i][j]); for(int i=1;i<=n;++i) { memset(vis,0,sizeof vis); dfs(1,i,i); } for(int i=1;i<=n;++i) if(!ans[i]) ++cnt; if(cnt) printf("0\n%d",cnt); else{ printf("1\n"); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j){ if(i>=S[j].l&&i<=S[j].r) f[i]=min(f[i],f[S[j].l-1]+1); } printf("%d",f[n]); } return 0; }
-
02016-10-25 10:59:09@
TM这是我第一次接触区间覆盖问题。。。
不过搞清楚之后觉得这个提高组最后一题有点水啊。。。
测试数据 #0: Accepted, time = 0 ms, mem = 4144 KiB, score = 10
测试数据 #1: Accepted, time = 0 ms, mem = 4144 KiB, score = 10
测试数据 #2: Accepted, time = 15 ms, mem = 4140 KiB, score = 10
测试数据 #3: Accepted, time = 0 ms, mem = 4140 KiB, score = 10
测试数据 #4: Accepted, time = 15 ms, mem = 4144 KiB, score = 10
测试数据 #5: Accepted, time = 0 ms, mem = 4148 KiB, score = 10
测试数据 #6: Accepted, time = 0 ms, mem = 4152 KiB, score = 10
测试数据 #7: Accepted, time = 0 ms, mem = 4156 KiB, score = 10
测试数据 #8: Accepted, time = 15 ms, mem = 4168 KiB, score = 10
测试数据 #9: Accepted, time = 46 ms, mem = 4208 KiB, score = 10
Accepted, time = 91 ms, mem = 4208 KiB, score = 100 -
02016-09-29 22:19:49@
这是一个区间完全覆盖问题
-
02016-08-24 16:09:31@
水题水一发
```c++
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;const int INF = 1000000000;
const int maxn = 500 + 10;struct Block {
int L, R;
bool operator < (const Block& rhs) const {
return L < rhs.L;
}
};int n, m;
int ans;
int vis[maxn];
int vis1[maxn][maxn];
int hg[maxn][maxn];
Block blocks[maxn];const int dr[] = { -1, 1, 0, 0};
const int dc[] = { 0, 0, 1, -1};void dfs (int r, int c, int n_block) {
if (r == n) {
if (!vis[c]) { vis[c] = 1; ans--;}
blocks[n_block].L = min(blocks[n_block].L, c);
blocks[n_block].R = max(blocks[n_block].R, c);
}
vis1[r][c] = n_block;
for (int d = 0; d < 4; d++)
if (hg[r][c] > hg[r+dr[d]][c+dc[d]] && vis1[r+dr[d]][c+dc[d]] != n_block)
dfs(r+dr[d], c+dc[d], n_block);
}int solve () {
int cnt = 0;
sort(blocks+1, blocks+m+1);
int L = 1, k = 1;
while (L <= m) {
cnt++;
int R = L;
for ( ; k <= m; k++) {
if (blocks[k].L > L) break;
R = max(R, blocks[k].R);
}
L = R + 1;
}
return cnt;
}int main ()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &hg[i][j]);for (int i = 1; i <= n; i++) hg[i][0] = hg[i][m+1] = INF;
for (int j = 1; j <= m; j++) hg[0][j] = hg[n+1][j] = INF;ans = m;
for (int i = 1; i <= m; i++) {
blocks[i].L = INF; blocks[i].R = -1;
if ((i == 1 || i == m) || (hg[1][i] >= hg[1][i-1] && hg[1][i] >= hg[1][i+1]))
dfs(1, i, i);
}if (ans > 0) printf("0\n%d\n", ans);
else printf("1\n%d\n", solve());
return 0;
}
``` -
02016-07-23 11:09:50@
求最小区间覆盖贪心即可啊。
-
02016-06-30 17:51:51@
其实只要一遍DFS就全求出来了。。。(然而区间覆盖写BFS用了临接表让我怀疑自己的脑袋。。。)
顺便问一下#2是什么为什么一直RE好不解。。。
#include<cstdio>
#include<iostream>
#include<cstring>
#define MAXN 510
using namespace std;int n,m;
int map[MAXN][MAXN];int l[MAXN][MAXN],r[MAXN][MAXN];
int vis[MAXN][MAXN];
int can[MAXN];int xx[4]={1,0,-1,0};
int yy[4]={0,1,0,-1};void dfs(int x,int y)
{
if(vis[x][y])return ;
vis[x][y]=1;
for(int i=0;i<4;i++)
if(map[x][y]>map[x+xx[i]][y+yy[i]])
{
dfs(x+xx[i],y+yy[i]);
l[x][y]=min(l[x][y],l[x+xx[i]][y+yy[i]]);
r[x][y]=max(r[x][y],r[x+xx[i]][y+yy[i]]);
}
if(x==n)
{
l[x][y]=min(l[x][y],y);
r[x][y]=max(r[x][y],y);
}
}int pos=0;
int fst[MAXN],next[MAXN*MAXN],to[MAXN*MAXN],poi=0;
void add(int op,int ed)
{next[++poi]=fst[op],fst[op]=poi,to[poi]=ed;return ;}
void build()
{
for(int i=0;i<pos;i++)
for(int j=i+1;j<pos;j++)
{
if(l[1][can[j]]<=r[1][can[i]]+1)add(can[i],can[j]);
else break;
}
}int q[MAXN],inq[MAXN];
int dep[MAXN];
int bfs()
{
memset(dep,0x7f,sizeof(dep));
int t=0,h=0,now;
while(l[1][can[t]]==1&&t<pos)q[t]=can[t],dep[can[t]]=1,inq[can[t]]=1,t++;
while(t!=h)
{
now=q[h++],h%=MAXN;
if(r[1][now]==m)return dep[now];
for(int i=fst[now];i;i=next[i])
{
if(dep[to[i]]>dep[now]+1)
{
dep[to[i]]=dep[now]+1;
if(!inq[to[i]])q[t++]=to[i],inq[to[i]]=1,t%=MAXN;
}
}
}
return 0;
}int main()
{
scanf("%d%d",&n,&m);
memset(map,0x7f,sizeof(map));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&map[i][j]);
memset(l,0x7f,sizeof(l));
memset(r,0,sizeof(r));
for(int i=1;i<=m;i++)
dfs(1,i);int cnt=0;
bool flag=false;
for(int i=1;i<=m;i++)
{
if(!flag&&r[1][i]!=0)can[pos++]=i;
if(!vis[n][i])
{
flag=true;
cnt++;
}
}
if(flag)
printf("0\n%d\n",cnt);
else
{
build();
printf("1\n%d\n",bfs());
}return 0;
} -
02016-06-17 13:45:35@
详细题解http://blog.csdn.net/Balala_Energy/article/details/51227646
```c++
#include <iostream>
#include <cstdio>
#include <queue>
#include <climits>
using namespace std;
const int L=501;
const int INF=INT_MAX;
int n,m; int map[L][L]; int F[L],LEFT[L],RIGHT[L];//main
struct zk { int x,y; }; queue<zk> q; bool used[L][L];//bfs
bool LEFTused[L][L],RIGHTused[L][L];//dfs
void read()
{
int i,j;
scanf("%d%d",&n,&m);
for (i=1;i<=m;i++)
F[i]=INF;
F[1]=1;
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
scanf("%d",&map[i][j]);
return;
}
bool bfs()
{
while(!q.empty()) q.pop();
zk temp; temp.y=1; int a,b,i;
for (i=1;i<=m;i++)
{
temp.x=i;
q.push(temp);
used[1][i]=1;
}
while(!q.empty())
{
temp=q.front();
a=temp.y; b=temp.x;
if (a>1&&!used[a-1][b]&&map[a][b]>map[a-1][b])
{
temp.y=a-1; temp.x=b;
q.push(temp); used[a-1][b]=1;
}
if (a<n&&!used[a+1][b]&&map[a][b]>map[a+1][b])
{
temp.y=a+1; temp.x=b;
q.push(temp); used[a+1][b]=1;
}
if (b>1&&!used[a][b-1]&&map[a][b]>map[a][b-1])
{
temp.y=a; temp.x=b-1;
q.push(temp); used[a][b-1]=1;
}
if (b<m&&!used[a][b+1]&&map[a][b]>map[a][b+1])
{
temp.y=a; temp.x=b+1;
q.push(temp); used[a][b+1]=1;
}
q.pop();
}
for (i=1;i<=m;i++)
if (!used[n][i])
return 0;
return 1;
}
void dfs1(int num,int x,int y,int front)
{
if(LEFTused[x][y]==1) return;
LEFTused[x][y]=1;
if(x==1) LEFT[y]=num;
if(x-1>=1&&front!=2&&map[x-1][y]>map[x][y]) dfs1(num,x-1,y,1);
if(x+1<=n&&front!=1&&map[x+1][y]>map[x][y]) dfs1(num,x+1,y,2);
if(y-1>=1&&front!=4&&map[x][y-1]>map[x][y]) dfs1(num,x,y-1,3);
if(y+1<=m&&front!=3&&map[x][y+1]>map[x][y]) dfs1(num,x,y+1,4);
return;
}
void dfs2(int num,int x,int y,int front)
{
if(RIGHTused[x][y]==1) return;
RIGHTused[x][y]=1;
if(x==1) RIGHT[y]=num;
if(x-1>=1&&front!=2&&map[x-1][y]>map[x][y]) dfs2(num,x-1,y,1);
if(x+1<=n&&front!=1&&map[x+1][y]>map[x][y]) dfs2(num,x+1,y,2);
if(y-1>=1&&front!=4&&map[x][y-1]>map[x][y]) dfs2(num,x,y-1,3);
if(y+1<=m&&front!=3&&map[x][y+1]>map[x][y]) dfs2(num,x,y+1,4);
return;
}
void dp()
{
int i,j;
for(i=2;i<=m;i++)
for(j=1;j<=m;j++)
{
if(LEFT[j]<=i&&RIGHT[j]>=i)
F[i]=min(F[i],F[LEFT[j]-1]+1);
else if(LEFT[j]>i)
break;
}
return;
}
void work()
{
int i,ans=0;
if (!bfs())
{
for (i=1;i<=m;i++)
if (!used[n][i])
ans++;
printf("0\n%d",ans);
}
else
{
for(i=1;i<=m;i++)
dfs1(i,n,i,0);
for(i=m;i>=1;i--)
dfs2(i,n,i,0);
dp();
printf("1\n%d",F[m]);
}
return;}
int main()
{
freopen("flow.in","r",stdin);
freopen("flow.out","w",stdout);
read();
work();
return 0;
}
``` -
02015-10-24 21:59:28@
第一次没有输入0和1直接爆零。。。。
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>using namespace std;
int n, m;
int h[5 05][505];
bool f0[505][505];
int l[505], r[505];
int f[505];
int q[500005], x[500005], y[500005];void bfs2(int i, int X, int Y) {
memset(x, 0, sizeof (x));
memset(y, 0, sizeof (y));
int now, end;
now = end = 0;
x[now] = X;
y[now] = Y;
while (now <= end) {
int x0, y0;
x0 = x[now];
y0 = y[now];
if (f0[x0][y0]) {
++now;
continue;
}
f0[x0][y0] = true;
if (x0 == n) {
l[i] = min(l[i], y0);
r[i] = max(r[i], y0);
}
if (h[x0][y0] > h[x0][y0 + 1] && y0 + 1 <= m) {
x[++end] = x0;
y[end] = y0 + 1;
}
if (h[x0][y0] > h[x0][y0 - 1] && y0 - 1 >= 1) {
x[++end] = x0;
y[end] = y0 - 1;
}
if (h[x0][y0] > h[x0 + 1][y0] && x0 + 1 <= n) {
x[++end] = x0 + 1;
y[end] = y0;
}
if (h[x0][y0] > h[x0 - 1][y0] && x0 - 1 >= 1) {
x[++end] = x0 - 1;
y[end] = y0;
}
++now;
}
}
void bfs1(int X, int Y) {
memset(x, 0, sizeof (x));
memset(y, 0, sizeof (y));
int now, end;
now = end = 0;
x[now] = X;
y[now] = Y;
while (now <= end) {
int x0, y0;
x0 = x[now];
y0 = y[now];
if (f0[x0][y0]) {
++now;
continue;
}
f0[x0][y0] = true;
if (h[x0][y0] > h[x0][y0 + 1] && y0 + 1 <= m) {
x[++end] = x0;
y[end] = y0 + 1;
}
if (h[x0][y0] > h[x0][y0 - 1] && y0 - 1 >= 1) {
x[++end] = x0;
y[end] = y0 - 1;
}
if (h[x0][y0] > h[x0 + 1][y0] && x0 + 1 <= n) {
x[++end] = x0 + 1;
y[end] = y0;
}
if (h[x0][y0] > h[x0 - 1][y0] && x0 - 1 >= 1) {
x[++end] = x0 - 1;
y[end] = y0;
}
++now;
}
}
void dfs2(int i, int x, int y) {
//printf("<<%d %d>>\n", x, y);
if (f0[x][y])
return ;
f0[x][y] = true;
if (x == n) {
l[i] = min(l[i], y);
r[i] = max(r[i], y);
}
if (h[x][y] > h[x][y + 1] && y + 1 <= m)
dfs2(i, x, y + 1);
if (h[x][y] > h[x][y - 1] && y - 1 >= 1)
dfs2(i, x, y - 1);
if (h[x][y] > h[x - 1][y] && x - 1 >= 1)
dfs2(i, x - 1, y);
if (h[x][y] > h[x + 1][y] && x + 1 <= n)
dfs2(i, x + 1, y);
}
void dfs1(int x, int y) {
if (f0[x][y])
return ;
f0[x][y] = true;
if (h[x][y] > h[x][y + 1] && y + 1 <= m)
dfs1(x, y + 1);
if (h[x][y] > h[x][y - 1] && y - 1 >= 1)
dfs1(x, y - 1);
if (h[x][y] > h[x - 1][y] && x - 1 >= 1)
dfs1(x - 1, y);
if (h[x][y] > h[x + 1][y] && x + 1 <= n)
dfs1(x + 1, y);
}
int main(int argc, const char *argv[]) {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
scanf("%d", &h[i][j]);
for (int i = 1; i <= m; ++i) {
bfs1(1, i);
}
int ans0 = m;
for (int i = 1; i <= m; ++i)
ans0 -= f0[n][i];
if (ans0) {
printf("0\n%d\n", ans0);
return 0;
}
for (int i = 1; i <= m; ++i) {
memset(f0, 0, sizeof (f0));
l[i] = 505;
bfs2(i, 1, i);
if (l[i] == 505) {
l[i] = 505;
r[i] = 505;
}
//printf("<%d %d>", l[i], r[i]);
}
for (int i = 1; i <= m; ++i) {
f[i] = 1000000000;
for (int j = 1; j <= m; ++j) {
if (l[j] <= i && i <= r[j])
f[i] = min(f[i], f[l[j] - 1] + 1);
}
}
printf("1\n%d\n", f[m]);
return 0;
} -
02015-10-09 23:12:47@
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN = 500 + 10;int h[MAXN][MAXN], vis[MAXN][MAXN], l[MAXN], r[MAXN], f[MAXN], got_w[MAXN];
int n, m;
int d1[5] = {0, 1, 0, -1};
int d2[5] = {1, 0, -1, 0};struct Status{
int x, y;
}start;queue<Status> q;
bool check(Status now, Status old){
int s = now.x, t = now.y;
if(vis[s][t] || s<1 || s>n || t<1 || t>m)
return 1;
if(h[s][t] >= h[old.x][old.y])
return 1;
return 0;
}void init_Bfs(){
for(int i=1; i<=m; i++){
Status ne;
ne.x = 1;
ne.y = i;
q.push(ne);
vis[1][i] = 1;
}
while(!q.empty()){
Status old = q.front();
q.pop();
for(int i=0; i<4; i++){
Status now = old;
now.x += d1[i];
now.y += d2[i];
if(check(now, old))
continue;
vis[now.x][now.y] = 1;
q.push(now);
}
}
}void Bfs(int s){
start.x = 1;
start.y = s;
q.push(start);
vis[1][s] = 1;
while(!q.empty()){
Status old = q.front();
q.pop();
for(int i=0; i<4; i++){
Status now = old;
now.x += d1[i];
now.y += d2[i];
if(check(now, old))
continue;
vis[now.x][now.y] = 1;
q.push(now);
}
}
}int main()
{
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
scanf("%d", &h[i][j]);
init_Bfs();
for(int i=1; i<=m; i++)
if(vis[n][i])
got_w[i]++;
int ans = 0;
for(int i=1; i<=m; i++)
if(!got_w[i])
ans++;
if(ans){
printf("0\n%d", ans);
return 0;
}
for(int i=1; i<=m; i++){
memset(vis, 0, sizeof(vis));
Bfs(i);
r[i] = l[i] = 0;
for(int j=1; j<=m; j++){
if(vis[n][j] && !r[i] && !l[i]){
l[i] = j;
r[i] = j;
}
else if(vis[n][j] && !vis[n][j+1] && l[i]){
r[i] = j;
break;
}
}
}
for(int i=1; i<=m; i++)
f[i] = 0x7fffffff;
for(int i=1; i<=m; i++)
for(int j=1; j<=m; j++)
if(l[j] <=i && r[j] >= i)
f[i] = min(f[l[j]-1]+1, f[i]);
printf("1\n%d", f[m]);
return 0;
}
两次BFS + DP -
02015-09-04 20:32:42@
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define inf 1<<30
using namespace std;
int n,m,ans,now;
int x1[5]={0,1,0,-1,0};
int y1[5]={0,0,1,0,-1};
int p[510][510],a[510][510];
int f[510];
struct qujian{
int l,r;
};
qujian g[510];
struct node{
int x,y;
};
node q[250100];
void bfs()
{
int head=0,tail=0;
for(int i=1;i<=m;i++){
p[1][i]=1;
q[++tail].x=1;
q[tail].y=i;
}
while(head<tail){
node u=q[++head];
for(int i=1;i<=4;i++){
node v;
v.x=u.x+x1[i];v.y=u.y+y1[i];
if(v.x>n||v.x<1||v.y>m||v.y<1) continue;
if(a[v.x][v.y]>=a[u.x][u.y]) continue;
if(p[v.x][v.y]) continue;
p[v.x][v.y]=1;
q[++tail]=v;
}
}
}
void bdfs(int x,int y)
{
p[x][y]=1;
if(x==n){
g[now].l=min(g[now].l,y);
g[now].r=max(g[now].r,y);
}
for(int i=1;i<=4;i++){
int xx=x+x1[i],yy=y+y1[i];
if(xx>n||xx<1||yy<1||yy>m) continue;
if(a[xx][yy]>=a[x][y]) continue;
if(!p[xx][yy])
bdfs(xx,yy);
}
}
int main()
{
freopen("flow.in","r",stdin);
freopen("flow.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
bfs();
int ans=0;
for(int i=1;i<=m;i++)
if(!p[n][i])
ans++;
if(ans){
printf("0\n");
printf("%d",ans);
return 0;
}
for(int i=1;i<=m;i++){
memset(p,0,sizeof(p));
now=i;
g[now].l=m+1;
g[now].r=0;
bdfs(1,now);
}
f[0]=0;
for(int i=1;i<=m;i++){
f[i]=inf;
for(int j=1;j<=m;j++)
if(i>=g[j].l&&i<=g[j].r)
f[i]=min(f[i],f[g[j].l-1]+1);
}
printf("1\n");
printf("%d",f[m]);
} -
02015-07-02 11:00:49@
难得又做出一道提高组最后一题...... 从样例中其实可以做出一个猜想:如果底层城市全都能被供水,那么对于任意一个蓄水站,它能供水的底层城市应当是一片连续的区域。这个猜想应该很好证明正确性,因为如果一个蓄水站供水的底层城市不是一片连续区域,那么中间就会出现”空缺“,这个“空缺”显然不可能由其它蓄水站来填补。因此解决这道题的思路是,先BFS判断是否有解,如果有解,用2次DFS+1次DP求解。
BFS:假设每一个湖边城市都有蓄水站,找出所有能被供水的点并标记。如果底层全被标记,则有解。否则没有解,输出0和未 被标记的个数。
DFS:用来找一个蓄水站供水的左边界和右边界。对于左边界,从底层1号开始搜索,能从底层K到到顶层某位置,则此位置供 水的左边界就是K。搜索时,已经过的点都不要再次经过。因为通过这些点要么无法到达顶层,要么到达顶层的左边界已 经确定且一定比现有的更小(举图中例子来说,底层1号经过高度为7的点到达顶层1号,顶层1号供水左边界为1号,那 么底层2号搜索时就不要再经过这个高度为7的点,因为通过它能到达的顶层1号,边界为1号,比2号小)。 对于右边 界则从底层K号开始,方法是一样的。用left[i]和right[i]表示i号蓄水站供水的左边界和右边界。
DP:f[i]表示到底层i号为止需要的蓄水站数目,初始化f[0]=0,f[1]=1,其他为无穷大。
可以得到下面这个式子:
f[i]=min{f[left[v]-1]+1} (left[v]<=i,right[v]>=i)
想法也比较简单,v蓄水站供水范围为left[v]~right[v],如果其中包含i,只需1个蓄水站就可对供水left[v]~i进行供水。那 么到i为止总共所需的蓄水站数量就为到left[v]前一个城市为止需要的蓄水站数量+1。当left[v]>i时直接跳出循环,去进行 i+1的循环(通过前面分析可知,left显然是一个不下降序列)。#include<stdio.h>
int map[501][501],bools[501][501],left[501]={0},right[501]={0};
int n,m;struct forbfs
{
int x,y;
}q[5001];int min(int a,int b)
{
if(a<b) return a;
else return b;
}void bfs( )
{
int head=0,tail=m;
int i,x,y;for(i=1;i<=m;i++)
{
q[i].x=1;
q[i].y=i;
bools[1][i]=1;
}while(head!=tail)
{head=(head+1)%5000;
x=q[head].x;
y=q[head].y;if(x-1>=1 && bools[x-1][y]==0 && map[x-1][y]<map[x][y])
{
bools[x-1][y]=1;
tail=(tail+1)%5000;
q[tail].x=x-1;
q[tail].y=y;
}if(x+1<=n && bools[x+1][y]==0 && map[x+1][y]<map[x][y])
{
bools[x+1][y]=1;
tail=(tail+1)%5000;
q[tail].x=x+1;
q[tail].y=y;}
if(y-1>=1 && bools[x][y-1]==0 && map[x][y-1]<map[x][y])
{
bools[x][y-1]=1;
tail=(tail+1)%5000;
q[tail].x=x;
q[tail].y=y-1;
}if(y+1<=m && bools[x][y+1]==0 && map[x][y+1]<map[x][y])
{
bools[x][y+1]=1;
tail=(tail+1)%5000;
q[tail].x=x;
q[tail].y=y+1;
}}
}void dfs1(int num,int x,int y,int front)
{
if(bools[x][y]==1) return;bools[x][y]=1;
if(x==1) left[y]=num;
if(x-1>=1 && front!=2 && map[x-1][y]>map[x][y]) dfs1(num,x-1,y,1);
if(x+1<=n && front!=1 && map[x+1][y]>map[x][y]) dfs1(num,x+1,y,2);
if(y-1>=1 && front!=4 && map[x][y-1]>map[x][y]) dfs1(num,x,y-1,3);
if(y+1<=m && front!=3 && map[x][y+1]>map[x][y]) dfs1(num,x,y+1,4);
}void dfs2(int num,int x,int y,int front)
{
if(bools[x][y]==1) return;bools[x][y]=1;
if(x==1) right[y]=num;
if(x-1>=1 && front!=2 && map[x-1][y]>map[x][y]) dfs2(num,x-1,y,1);
if(x+1<=n && front!=1 && map[x+1][y]>map[x][y]) dfs2(num,x+1,y,2);
if(y-1>=1 && front!=4 && map[x][y-1]>map[x][y]) dfs2(num,x,y-1,3);
if(y+1<=m && front!=3 && map[x][y+1]>map[x][y]) dfs2(num,x,y+1,4);
}int main( )
{
int i,j,bfans=0,dp[501];scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
bools[i][j]=0;
}//
bfs( );
for(i=1;i<=m;i++)
if(bools[n][i]==0) bfans++;if(bfans!=0) {printf("0\n%d",bfans);goto endl;}
//
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
bools[i][j]=0;for(i=1;i<=m;i++)
dfs1(i,n,i,0);//
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
bools[i][j]=0;for(i=m;i>=1;i--)
dfs2(i,n,i,0);//
for(i=1;i<=m;i++)
dp[i]=1000008;dp[0]=0;
dp[1]=1;for(i=2;i<=m;i++)
{
for(j=1;j<=m;j++)
{
if(left[j]<=i && right[j]>=i) dp[i]=min(dp[i],dp[left[j]-1]+1);
else if(left[j]>i) break;
}
}printf("1\n%d",dp[m]);
//
endl:return 0;
} -
02014-11-30 17:14:14@
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
bool l[501][501],w[501];
int e[501][501],f[501],m,n;
class s
{
public:
int l,r;
s()
{
l=0x7fffffff;
r=0;
}
}a[501];
bool operator<(s a,s b)
{
return a.r<b.r;
}
void o(int s,int x,int y)
{
int h;
if(x==n)
{
w[y]=1;
a[s].l=min(a[s].l,y);
a[s].r=max(a[s].r,y);
}
l[x][y]=1;
h=e[x][y];
if(x<n&&e[x+1][y]<h&&!l[x+1][y])
o(s,x+1,y);
if(x>1&&e[x-1][y]<h&&!l[x-1][y])
o(s,x-1,y);
if(y<m&&e[x][y+1]<h&&!l[x][y+1])
o(s,x,y+1);
if(y>1&&e[x][y-1]<h&&!l[x][y-1])
o(s,x,y-1);
}
main()
{
int i,j,x=0,t=1;
cin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
cin>>e[i][j];
for(i=1;i<=m;i++)
{
if(i>1&&e[1][i]<e[1][i-1])
continue;
if(i<m&&e[1][i]<e[1][i+1])
continue;
memset(l,0,sizeof(l));
o(i,1,i);
}
for(i=1;i<=m;i++)
if(w[i])
x++;
if(x<m)
{
cout<<"0\n"<<m-x;
return 0;
}
sort(a+1,a+1+m);
for(i=1;i<=m;i++)
f[i]=0x7fffffff/2;
for(i=1;i<=m;i++)
{
if(i<a[t].r)
continue;
while(t<=m&&i>a[t].r)
t++;
while(i==a[t].r)
f[i]=min(f[i],f[a[t++].l-1]+1);
for(j=1;j<i;j++)
f[j]=min(f[j],f[i]);
}
cout<<"1\n"<<f[m];
} -
02014-11-04 20:59:22@
const d:array[1..4,1..2]of shortint=((0,1),(0,-1),(-1,0),(1,0));
var
i,j,k,n,m,t,ans:longint;
l,r:array[1..500]of longint;
a:array[1..500,1..500]of longint;
f:array[0..501,0..501]of boolean;
procedure pre;
var i:longint;
begin
fillchar(f,sizeof(f),0);
for i:=1 to m do
begin f[0,i]:=true; f[n+1,i]:=true end;
for i:=1 to n do
begin f[i,0]:=true; f[i,m+1]:=true end
end;
PROCEDURE qs(p,q:word);
VAR
i,j,k1,k2,t:longint;
BEGIN
i:=p; j:=q;
k1:=l[(p+q)shr 1];
k2:=r[(p+q)shr 1];
REPEAT
WHILE (l[i]<k1)or(l[i]=k1)and(r[i]>k2) DO inc(i);
WHILE (l[j]>k1)or(l[j]=k1)and(r[j]<k2) DO dec(j);
IF i<=j
THEN BEGIN
t:=l[i]; l[i]:=l[j]; l[j]:=t;
t:=r[i]; r[i]:=r[j]; r[j]:=t;
inc(i); dec(j)
END;
UNTIL i>j;
IF j>p THEN qs(p,j);
IF i<q THEN qs(i,q)
END;
procedure floodfill(x,y:integer);
var
i,nx,ny:integer;
begin
f[x,y]:=true;
for i:=1 to 4 do
begin
nx:=x+d[i,1]; ny:=y+d[i,2];
if not f[nx,ny]and(a[nx,ny]<a[x,y])
then floodfill(nx,ny)
end
end;
begin
readln(n,m); pre;
for i:=1 to n do
for j:=1 to m do read(a[i,j]);
if n>1 then
begin
for i:=1 to m do
if not f[1,i] then floodfill(1,i);
for i:=1 to m do
if not f[n,i] then inc(k);
if k>0 then
begin writeln(0); write(k); exit end;
pre
end;
for i:=1 to m do
begin
floodfill(1,i);
for j:=1 to m+1 do
if f[n,j] then break;
if j<=m then l[i]:=j;
for j:=m downto 0 do
if f[n,j] then break;
if j>0 then r[i]:=j; pre
end;
qs(1,m); i:=1; ans:=1; j:=0;
while l[i]=0 do inc(i);
repeat
inc(j); l[j]:=l[i]; r[j]:=r[i];
while l[i]=l[j] do inc(i);
until i>m;
t:=m; m:=j; i:=1;
if r[i]<t then
repeat
j:=r[i]; n:=0;
for i:=i+1 to m do
begin
if l[i]>j+1 then break;
if r[i]>n then
begin n:=r[i]; k:=i end
end;
i:=k; j:=n; inc(ans)
until n=t;
writeln(1); write(ans)
end. -
02014-10-25 13:34:25@
NOIP2014赛前AC留念
const x:array[1..4] of integer=(-1,1,0,0);
y:array[1..4] of integer=(0,0,-1,1);var c:array[0..700,1..2] of longint;
linex,liney:array[0..500000] of longint;
h:array[0..700,0..700] of longint;
n,m,nowx,j,nowy,temp,i,ans:longint;
use:array[0..700,0..700] of boolean;
f:array[0..701] of longint;function can(a,b:longint):boolean;
begin
if h[a,b]<h[nowx,nowy] then
if (a>0) and (a<=n) and (b>0) and (b<=m) and (not use[a,b]) then
exit(true);
exit(false);
end;procedure bfs;
var opened,closed,i,j:longint;
begin
opened:=0;
closed:=m;
for i:=1 to m do
begin
linex[i]:=1;
liney[i]:=i;
use[1,i]:=true;
end;
repeat
inc(opened);
nowx:=linex[opened];
nowy:=liney[opened];
for i:=1 to 4 do
begin
if can(nowx+x[i],nowy+y[i]) then
begin
use[nowx+x[i],nowy+y[i]]:=true;
inc(closed);
linex[closed]:=nowx+x[i];
liney[closed]:=nowy+y[i];
end;
end;
until opened>=closed;
for j:=1 to m do
if not use[n,j] then inc(ans);
end;function min(a,b:longint):longint;
begin
if a<b then exit(a)
else exit(b);
end;procedure dfs(k,p:longint);
var i:longint;
begin
use[k,p]:=true;if k=n then
begin
if p>c[temp,2] then c[temp,2]:=p;
if (p<c[temp,1]) or (c[temp,1]=0) then c[temp,1]:=p;
end;for i:=1 to 4 do
begin
nowx:=k;
nowy:=p;
if can(k+x[i],p+y[i]) then
begindfs(k+x[i],p+y[i]);
end;
end;end;
begin
//assign(input,'flow.in');
//assign(output,'flow.out');
//reset(input);
//rewrite(output);
readln(n,m);
for i:=1 to n do
for j:=1 to m do read(h[i,j]);
bfs;
if ans>0 then
begin
writeln(0);
writeln(ans);
//close(input);
//close(output);
halt;
end;for i:=1 to m do
begin
temp:=i;
fillchar(use,sizeof(use),false);
dfs(1,i);
end;for i:=1 to m do
begin
f[i]:=maxlongint;
for j:=1 to m do
if c[j,2]>=i then
if c[j,1]<=i then
if f[c[j,1]-1]<>maxlongint then
f[i]:=min(f[c[j,1]-1]+1,f[i]);
end;writeln(1);
writeln(f[m]);
//close(input);
//close(output);
end. -
02014-08-04 12:38:55@
windows下DFS过不了第三个TAT
-
02014-07-31 22:57:51@
#include <cstdio>
#include <iostream>
#include <cstring>
#define INF (~0U>>4)
using namespace std;
int n,m;
int h[502][502];
int f[502];
bool arr[502];
struct Q
{
int x,y;
}q[1000006];
int ll[502][502],rr[502][502];
int ans1=0;
bool vst[502][502];
const int px[4]={0,1,0,-1},py[4]={1,0,-1,0};
bool Check(int x,int y)
{
if (x<0 || y<0) return false;
if (x>n || y>m) return false;
if (vst[x][y]) return false;
return true;
}
void Bfs(int u)
{
int l=0,r=0;
q[++r].x=1,q[r].y=u;
vst[1][u]=true;
while (l!=r)
{
++l;
l%=1000006;
Q x=q[l];
for (int i=0;i<4;i++)
if (Check(x.x+px[i],x.y+py[i]) && h[x.x][x.y]>h[x.x+px[i]][x.y+py[i]])
{
vst[x.x+px[i]][x.y+py[i]]=true;
++r,r%=1000006;
q[r].x=x.x+px[i],q[r].y=x.y+py[i];
}
}
}
void Bfs1(int u)
{
int l=0,r=0;
q[++r].x=n,q[r].y=u;
vst[n][u]=true;
ll[n][u]=u;
while (l!=r)
{
++l;
l%=1000006;
Q x=q[l];
for (int i=0;i<4;i++)
if (Check(x.x+px[i],x.y+py[i]) && h[x.x][x.y]<h[x.x+px[i]][x.y+py[i]])
{
vst[x.x+px[i]][x.y+py[i]]=true;
ll[x.x+px[i]][x.y+py[i]]=u;
++r,r%=1000006;
q[r].x=x.x+px[i],q[r].y=x.y+py[i];
}
}
}
void Bfs2(int u)
{
int l=0,r=0;
q[++r].x=n,q[r].y=u;
vst[n][u]=true;
rr[n][u]=u;
while (l!=r)
{
++l;
l%=1000006;
Q x=q[l];
for (int i=0;i<4;i++)
if (Check(x.x+px[i],x.y+py[i]) && h[x.x][x.y]<h[x.x+px[i]][x.y+py[i]])
{
vst[x.x+px[i]][x.y+py[i]]=true;
rr[x.x+px[i]][x.y+py[i]]=u;
++r,r%=1000006;
q[r].x=x.x+px[i],q[r].y=x.y+py[i];
}
}}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) scanf("%d",h[i]+j);
for (int i=1;i<=m;i++) if (!vst[1][i])Bfs(i);
int x=0;
for (int i=1;i<=m;i++)
x+=vst[n][i];
if (x!=m)
{
puts("0");
printf("%d\n",m-x);
return 0;
}
memset(vst,0,sizeof(vst));
for (int i=1;i<=m;i++)
if (!vst[n][i])Bfs1(i);
memset(vst,0,sizeof(vst));
for (int i=m;i;i--)
if (!vst[n][i])Bfs2(i);
for (int i=1;i<=m;i++)
if (ll[1][i]) f[ll[1][i]]=max(f[ll[1][i]],rr[1][i]);
int last=f[1],r=f[1];
int ans=1;
for (int i=1;i<=m && last<m;i++)
{
if (i>last) last=max(f[i],r),ans++;
r=max(r,f[i]);
}
puts("1");
printf("%d\n",ans);
return 0;
} -
02013-11-02 17:01:32@
速度还可以吧。。线段覆盖写了O(n log n)的。
编译成功测试数据 #0: Accepted, time = 0 ms, mem = 5900 KiB, score = 10
测试数据 #1: Accepted, time = 0 ms, mem = 5900 KiB, score = 10
测试数据 #2: Accepted, time = 19 ms, mem = 5904 KiB, score = 10
测试数据 #3: Accepted, time = 0 ms, mem = 5904 KiB, score = 10
测试数据 #4: Accepted, time = 0 ms, mem = 5908 KiB, score = 10
测试数据 #5: Accepted, time = 0 ms, mem = 5916 KiB, score = 10
测试数据 #6: Accepted, time = 0 ms, mem = 5916 KiB, score = 10
测试数据 #7: Accepted, time = 15 ms, mem = 5908 KiB, score = 10
测试数据 #8: Accepted, time = 0 ms, mem = 5932 KiB, score = 10
测试数据 #9: Accepted, time = 31 ms, mem = 5988 KiB, score = 10
Accepted, time = 65 ms, mem = 5988 KiB, score = 100http://hi.baidu.com/greencloud/item/939e36ce914e5726ef466562
-
02013-10-28 20:45:19@
O(n^2)算法,先dfs判断可行,然后再dfs求出每个临湖城市能覆盖的区间,最后DP求解,三步均为n^2。对于pascal来说还算是漂亮的时间:
编译成功
测试数据 #0: Accepted, time = 0 ms, mem = 6144 KiB, score = 10
测试数据 #1: Accepted, time = 0 ms, mem = 6148 KiB, score = 10
测试数据 #2: Accepted, time = 62 ms, mem = 6144 KiB, score = 10
测试数据 #3: Accepted, time = 0 ms, mem = 6152 KiB, score = 10
测试数据 #4: Accepted, time = 0 ms, mem = 6148 KiB, score = 10
测试数据 #5: Accepted, time = 15 ms, mem = 6144 KiB, score = 10
测试数据 #6: Accepted, time = 15 ms, mem = 6148 KiB, score = 10
测试数据 #7: Accepted, time = 15 ms, mem = 6144 KiB, score = 10
测试数据 #8: Accepted, time = 15 ms, mem = 6148 KiB, score = 10
测试数据 #9: Accepted, time = 93 ms, mem = 6160 KiB, score = 10
Accepted, time = 215 ms, mem = 6160 KiB, score = 100uses math;
type
rec=record
x,y:longint;
end;
var
n,m,i,j,top,ans:longint;
ok:array[0..501,0..501]of boolean;
a:array[0..501,0..501]of longint;
ll,rr:array[0..501,0..501]of longint;
st:array[0..250000]of rec;
f:Array[0..501]of longint;procedure check(x,y,i,j:longint);
begin
if (i<1)or(i>n)or(j<1)or(j>m) then exit;
if a[x,y]<=a[i,j] then exit;
if ok[i,j] then exit;
inc(top); ok[i,j]:=true;
st[top].x:=i; st[top].y:=j;
end;
procedure dfs(x,y:longint);
begin
st[1].x:=x; st[1].y:=y; top:=1; ok[x,y]:=true;
while top>0 do
begin
x:=st[top].x; y:=st[top].y; dec(top);
check(x,y,x,y-1); check(x,y,x,y+1);
check(x,y,x-1,y); check(x,y,x+1,y);
end;
end;function check2(x,y,i,j:longint):boolean;
begin
if (i<1)or(i>n)or(j<1)or(j>m) then exit(false);
if a[x,y]<=a[i,j] then exit(false);
exit(true);
end;
procedure dfs2(x,y:longint);
begin
if ok[x,y] then exit;
ok[x,y]:=true;
if check2(x,y,x,y-1) then begin
dfs2(x,y-1);
ll[x,y]:=min(ll[x,y],ll[x,y-1]);
rr[x,y]:=max(rr[x,y],rr[x,y-1]);
end;
if check2(x,y,x,y+1) then begin
dfs2(x,y+1);
ll[x,y]:=min(ll[x,y],ll[x,y+1]);
rr[x,y]:=max(rr[x,y],rr[x,y+1]);
end;
if check2(x,y,x-1,y) then begin
dfs2(x-1,y);
ll[x,y]:=min(ll[x,y],ll[x-1,y]);
rr[x,y]:=max(rr[x,y],rr[x-1,y]);
end;
if check2(x,y,x+1,y) then begin
dfs2(x+1,y);
ll[x,y]:=min(ll[x,y],ll[x+1,y]);
rr[x,y]:=max(rr[x,y],rr[x+1,y]);
end;
end;begin
readln(n,m);
for i:=1 to n do
for j:=1 to m do
read(a[i,j]);
fillchar(ok,sizeof(ok),false);
for j:=1 to m do
if not ok[1,j] then dfs(1,j);
ans:=0;
for j:=1 to m do
if not ok[n,j] then inc(ans);
if ans>0 then begin writeln(0); writeln(ans); halt; end;
fillchar(ll,sizeof(ll),127);
fillchar(rr,sizeof(rr),0);
for i:=1 to m do begin ll[n,i]:=i; rr[n,i]:=i; end;
fillchar(ok,sizeof(ok),false);
for i:=1 to m do
if not ok[1,i] then dfs2(1,i);
fillchar(f,sizeof(f),127);
f[0]:=0;
for i:=1 to m do
for j:=ll[1,i]-1 to rr[1,i]-1 do
f[rr[1,i]]:=min(f[rr[1,i]],f[j]+1);
writeln(1);
writeln(f[m]);
end.就是代码略长……