码迷,mamicode.com
首页 > 编程语言 > 详细

算法复习——区间dp

时间:2017-09-19 21:26:19      阅读:274      评论:0      收藏:0      [点我收藏+]

标签:div   out   color   i++   ems   algo   问题   head   namespace   

技术分享

技术分享技术分享技术分享

感觉对区间dp也不好说些什么直接照搬讲义了2333

例题:

1.引水入城(洛谷1514)

技术分享技术分享

技术分享

这道题先开始看不出来到底和区间dp有什么卵关系····

首先肯定是bfs暴力判一判可以覆盖到哪些城市····无解直接输出···有解得话就要想想了····

这道题关键是要发现··如果一个蓄水池所在城市可以覆盖到一些沙漠城市···那么这些沙漠城市肯定是一段····不然假设有一个城市是断开的而两边都被同一个蓄水池流出的水覆盖,这个城市四周的城市都肯定比它矮···(不理解举个反例吧···反正我举不出来)···然后就可以找到每一个蓄水池它对应的可以覆盖的区间···转化成一个关于线段覆盖的区间dp问题·····即可求解(dp方程看代码吧)

另外这道题bfs时注意是入队时打标记不然会爆···另外判条件时先判越界没有···

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1005;
const int gox[4]={1,0,-1,0};
const int goy[4]={0,1,0,-1};
struct node
{ 
  int x,y;
}que[N*N];
struct node1
{
  int l,r;
}g[N];
int map[N][N],n,m,tail,head,f[N];
bool visit[N][N];
inline int R()
{
  char c;int f=0;
  for(c=getchar();c<0||c>9;c=getchar());
  for(;c<=9&&c>=0;c=getchar())
    f=(f<<3)+(f<<1)+c-0;
  return f;
}
inline void bfs()
{
  head=1,tail=0;
  for(int i=1;i<=m;i++)
  {
    que[++tail].x=1;que[tail].y=i;
    visit[que[head].x][que[head].y]=true;
  }
  for(;head<=tail;head++)
  {
    for(int i=0;i<=3;i++)
    {
      visit[que[head].x][que[head].y]=true;
      int vx=que[head].x+gox[i];int vy=que[head].y+goy[i];
      if(vx<1||vx>n||vy<1||vy>m||visit[vx][vy]||map[vx][vy]>=map[que[head].x][que[head].y])  continue;
      node temp; 
      temp.x=vx,temp.y=vy;que[++tail]=temp;
      visit[temp.x][temp.y]=true;
    }
  }
}
inline void dfs(int x,int y,int u)
{
  visit[x][y]=true;
  if(x==n)
    g[u].l=min(g[u].l,y),g[u].r=max(g[u].r,y);
  for(int i=0;i<=3;i++)
  {
    int vx=x+gox[i];int vy=y+goy[i];
    if(visit[vx][vy]||vx<1||vx>n||vy<1||vy>m||map[vx][vy]>=map[x][y])  continue;
    dfs(vx,vy,u);
  }
}
int main()
{
  //("a.in","r",stdin);
  memset(f,inf,sizeof(f));
  n=R(),m=R();
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      map[i][j]=R();
  bfs();
  int temp=0;
  for(int i=1;i<=m;i++)
    if(visit[n][i]==true)  temp++;
  if(temp!=m)
  {
    cout<<"0"<<endl;
    cout<<m-temp<<endl;
    return 0;
  }
  for(int i=1;i<=m;i++)
  {
    memset(visit,false,sizeof(visit));
    g[i].l=m+1;g[i].r=0;
    dfs(1,i,i);
  }
  f[0]=0;
  for(int i=1;i<=m;i++)
    for(int j=1;j<=m;j++)
      if(g[j].l<=i&&g[j].r>=i)
        f[i]=min(f[i],f[g[j].l-1]+1);
  cout<<"1"<<endl;
  cout<<f[m]<<endl;
  return 0;
} 

 

算法复习——区间dp

标签:div   out   color   i++   ems   algo   问题   head   namespace   

原文地址:http://www.cnblogs.com/AseanA/p/7553926.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!