zoukankan      html  css  js  c++  java
  • WOJ 1546 Maze 图论上的状态压缩DP

    http://acm.whu.edu.cn/land/problem/detail?problem_id=1546

    这个题目还是聪哥教的方法过的

    首先搜索是必须的,而且通过搜索来缩点,这些应该要想到,即把图上的起点和终点还有能量点进行标记,之后用bfs找到这些个点的最短路,最多只有12个点,这样对12个点进行状态压缩DP,状态压缩这部分不是很好写

    用dp[i][j]表示在状态i的情况下,此刻在j点落脚的最大能量数,则先枚举i再枚举j,再枚举k,k代表已经存在于i里面的点 每次从dp[i][k]过度到dp[i][j],从dp[i][k]+dis[k][j]+dis[j][m+1]<=L(m+1是终点)则可以进行转移,取得该能量。

    整个状态转移走完找出最大的能量数跟需求判断下即可得出结果

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define INF 1<<30
    using namespace std;
    char g[55][55];
    int vis[55][55];
    int num[15];
    int d[15][15];
    int dp[1<<12][15];
    int dis[1<<12][15];
    int w,h,l,m,s;
    struct node
    {
        int x,y,deep;
    } v[15];
    int dir[][2]={{0,1},{0,-1},{1,0},{-1,0}};
    void bfs(int x,int y)
    {
        node sx=node{x,y,0};
        queue<node> q;
        q.push(sx);
        memset(vis,0,sizeof vis);
        char cc=g[x][y];
        while (!q.empty())
        {
            node nx=q.front();
            q.pop();
            if (vis[nx.x][nx.y]) continue;
            vis[nx.x][nx.y]=1;
            for (int i=0;i<4;i++)
            {
                node qx=(node){nx.x+dir[i][0],nx.y+dir[i][1],nx.deep+1};
                if (qx.x<0 || qx.x>=h || qx.y<0 || qx.y>=w) continue;
                if (vis[qx.x][qx.y]) continue;
                char ch=g[qx.x][qx.y];
                if (ch=='#') continue;
                if (ch>='a' && ch<='a'+m+1)
                {
                    if (d[cc-'a'][ch-'a']>qx.deep)
                        d[cc-'a'][ch-'a']=qx.deep;
                    //cout<<cc-'a'<<" "<<ch-'a'<<" "<<d[cc-'a'][ch-'a']<<" aaa"<<endl;
                }
                q.push(qx);
            }
        }
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while (t--)
        {
            scanf("%d%d%d%d%d",&w,&h,&l,&m,&s);
            for (int i=1;i<=m;i++)
                scanf("%d",&num[i]);
            for (int i=0;i<h;i++){
                scanf("%s",g[i]);
            }
            int tmp=1;
            for (int i=0;i<h;i++)
                for (int j=0;j<w;j++)
                 d[i][j]=INF;
            for (int i=0;i<h;i++)
            {
                for (int j=0;j<w;j++)
                {
                    if (g[i][j]=='$')
                      g[i][j]='a';
                    if (g[i][j]=='@')
                      g[i][j]='a'+(tmp++);
                    if (g[i][j]=='<')
                      g[i][j]='a'+m+1;
                }
            }
            for (int i=0;i<=h;i++)
            {
                for (int j=0;j<=w;j++)
                {
                    if (g[i][j]>='a' && g[i][j]<='a'+m+1){
                    // cout<<i<<" "<<j<<endl;
                     bfs(i,j);
    //进行BFS缩点                 //cout<<endl;
                    }
                }
            }
            int ret=0;
    
    //对可以直接取得点先取了
    for (int i=1;i<=m;i++) { if (d[i][m+1]<=l/2) { ret+=num[i]; num[i]=0; } } int ans=0; memset(dp,-1,sizeof dp); memset(dis,0,sizeof dis); for (int i=0;i<m;i++) { dis[1<<i][i+1]=d[0][i+1]; if (d[0][i+1]+d[i+1][m+1]<=l){ ans=max(ans,num[i+1]); dp[1<<i][i+1]=num[i+1]; } } for (int i=1;i<(1<<m);i++) { for (int j=1;j<=m;j++) { if (!(1<<(j-1) & i)) continue; int tmp=i-(1<<j-1); if (tmp==0) continue; int td=d[j][m+1]; for (int k=1;k<=m;k++) { if (dp[tmp][k]==-1) continue; if (!(tmp&(1<<k-1))) continue; if (dis[tmp][k]+d[k][j]<=l-td) { if (dp[i][j]==-1) { dp[i][j]=dp[tmp][k]+num[j]; dis[i][j]=dis[tmp][k]+d[k][j]; } else if (dp[i][j]<dp[tmp][k]+num[j]) { dp[i][j]=dp[tmp][k]+num[j]; dis[i][j]=dis[tmp][k]+d[k][j]; } } } ans=max(ans,dp[i][j]); } } if (ret+ans<s || d[0][m+1]>l) puts("NO"); else puts("YES"); } return 0; }
  • 相关阅读:
    14071702(SkeletalControl_Limb)
    14072202(带IK的Recoil)
    UE3植被工具-支持刷Actor)
    UDK:AdventureKit 攀爬系统
    16082402(SkeletalMesh的绘制流程)
    windows下安装nodejs
    laravel迁移文件
    laravel的资源路由resource
    sleep参数是整型还是小数
    node.js和npm的关系
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3646253.html
Copyright © 2011-2022 走看看