codeforces 152E Garden(狀態壓縮dp)

題目鏈接

E. Garden
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Vasya has a very beautiful country garden that can be represented as an n × m rectangular field divided into n·m squares. One beautiful day Vasya remembered that he needs to pave roads between k important squares that contain buildings. To pave a road, he can cover some squares of his garden with concrete.

For each garden square we know number aij that represents the number of flowers that grow in the square with coordinates (i, j). When a square is covered with concrete, all flowers that grow in the square die.

Vasya wants to cover some squares with concrete so that the following conditions were fulfilled:

  • all k important squares should necessarily be covered with concrete
  • from each important square there should be a way to any other important square. The way should go be paved with concrete-covered squares considering that neighboring squares are squares that have a common side
  • the total number of dead plants should be minimum

As Vasya has a rather large garden, he asks you to help him.

Input

The first input line contains three integers n, m and k (1 ≤ n, m ≤ 100, n·m ≤ 200, 1 ≤ k ≤ min(n·m, 7)) — the garden's sizes and the number of the important squares. Each of the next n lines contains m numbers aij (1 ≤ aij ≤ 1000) — the numbers of flowers in the squares. Next k lines contain coordinates of important squares written as "x y" (without quotes) (1 ≤ x ≤ n, 1 ≤ y ≤ m). The numbers written on one line are separated by spaces. It is guaranteed that all k important squares have different coordinates.

Output

In the first line print the single integer — the minimum number of plants that die during the road construction. Then print n lines each containing m characters — the garden's plan. In this plan use character "X" (uppercase Latin letter X) to represent a concrete-covered square and use character "." (dot) for a square that isn't covered with concrete. If there are multiple solutions, print any of them.

Sample test(s)
input
3 3 2
1 2 3
1 2 3
1 2 3
1 2
3 3
output
9
.X.
.X.
.XX
input
4 5 4
1 4 5 1 2
2 2 2 2 7
2 4 1 4 5
3 2 1 7 1
1 1
1 5
4 1
4 4
output
26
X..XX
XXXX.
X.X..
X.XX.

非常好的一道狀態壓縮動態規劃的題目!!

題意:n*m的網格圖,每個格子都有一定價值的花aij。有k個重要的格子,現在可以用水泥來填一個格子,填完以後損失這個格子的花的價值。相鄰兩個被水泥填的格子可以相互連通。問讓k個重要的格子連通,最少要損失的花的價值?並輸出方案。

題解:由於k<=7,所以考慮狀態壓縮動態規劃來求解。

用dp[mask][v]表示mask狀態(k位二進制狀態,第i位爲1表示選,否則不選)的重要的點相互連通,第v個點必選的最小花費。

轉移有兩種:

第一:點v可以把當前連通塊分成兩個不同的連通塊,則:

dp[mask][v] = min ( dp[ submask ][ v ] + dp[ mask^submask ][ v ] - cost( v ) )

第二:如果點v不能把當前連通塊分成兩個塊,則:

dp[mask][v]=min( dp[ mask ][ u ] + dis( u,v ) - cost( u ) ) ;

dis(u,v)表示連接u,v的最小花費,cost( u ) 表示點u的花費

代碼如下:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<string.h>
#include<string>
#include<stdlib.h>
typedef __int64 LL;
typedef unsigned __int64 LLU;
const int nn=110;
const int inf=0x3fffffff;
const LL inf64=(LL)inf*inf;
const double eps=1e-8;
using namespace std;
int n,m,k;
int a[nn][nn];
int dp[(1<<7)+10][nn][nn];
bool use[nn][nn];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
struct node
{
    int mask,x,y;
    node(){}
    node(int mmask,int xx,int yy)
    {
        mask=mmask,x=xx,y=yy;
    }
};
node pre[(1<<7)+10][nn][nn];
queue<node>que;
bool inque[(1<<7)+10][nn][nn];
void solve(int mask,int x,int y)
{
    if(pre[mask][x][y].mask==-1)
        return ;
    if(pre[mask][x][y].mask==0)
    {
        solve(pre[mask][x][y].x,x,y);
        solve(pre[mask][x][y].y,x,y);
    }
    else
    {
        use[x][y]=true;
        solve(mask,pre[mask][x][y].x,pre[mask][x][y].y);
    }
}
int main()
{
    int i,j,x,y,e;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        memset(use,false,sizeof(use));
        memset(inque,false,sizeof(inque));
        for(e=0;e<(1<<k);e++)
        {
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=m;j++)
                {
                    dp[e][i][j]=inf;
                    pre[e][i][j]=node(-1,-1,-1);
                }
            }
        }
        for(i=0;i<k;i++)
        {
            scanf("%d%d",&x,&y);
            dp[(1<<i)][x][y]=a[x][y];
            use[x][y]=true;
            que.push(node(1<<i,x,y));
            inque[(1<<i)][x][y]=true;
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                if(!use[i][j])
                {
                    dp[0][i][j]=a[i][j];
                    que.push(node(0,i,j));
                    inque[0][i][j]=true;
                }
            }
        }
        node sta;
        while(que.size())
        {
            sta=que.front();
            que.pop();
            inque[sta.mask][sta.x][sta.y]=false;
            for(e=1;e<(1<<k);e++)
            {
                if((e&sta.mask)==0)
                {
                    if(dp[e^sta.mask][sta.x][sta.y]>dp[sta.mask][sta.x][sta.y]+dp[e][sta.x][sta.y]-a[sta.x][sta.y])
                    {
                        pre[e^sta.mask][sta.x][sta.y]=node(0,sta.mask,e);
                        dp[e^sta.mask][sta.x][sta.y]=dp[sta.mask][sta.x][sta.y]+dp[e][sta.x][sta.y]-a[sta.x][sta.y];
                        if(!inque[e^sta.mask][sta.x][sta.y])
                        {
                            inque[e^sta.mask][sta.x][sta.y]=true;
                            que.push(node(e^sta.mask,sta.x,sta.y));
                        }
                    }
                }
            }
            for(i=0;i<4;i++)
            {
                int dx=sta.x+dir[i][0];
                int dy=sta.y+dir[i][1];
                if(dx>=1&&dx<=n&&dy>=1&&dy<=m)
                {
                    if(dp[sta.mask][dx][dy]>dp[sta.mask][sta.x][sta.y]+a[dx][dy])
                    {
                        pre[sta.mask][dx][dy]=node(1,sta.x,sta.y);
                        dp[sta.mask][dx][dy]=dp[sta.mask][sta.x][sta.y]+a[dx][dy];
                        que.push(node(sta.mask,dx,dy));
                        inque[sta.mask][dx][dy]=true;
                    }
                }
            }
        }
        int ans=inf;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                if(dp[(1<<k)-1][i][j]<ans)
                {
                    ans=dp[(1<<k)-1][i][j];
                    sta=node((1<<k)-1,i,j);
                }
            }
        }
        printf("%d\n",ans);
        solve(sta.mask,sta.x,sta.y);
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                printf("%c",use[i][j]?'X':'.');
            }
            puts("");
        }
    }
    return 0;
}



發佈了213 篇原創文章 · 獲贊 4 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章