Circling Round Treasures(codeforces 375c)

题意:要求在一张网格图上走出一条闭合路径,不得将炸弹包围进去,使围出的总价值减去路径长度最大。

/*
  类似于poj3182的做法,只不过出现了多个点,那么就用状态压缩的方法记录一个集合即可。
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
char map[25][25],ch[25];
int n,m,sx,sy,tx,ty,nx,ny,gx[10],gy[10],val[10],w[1010],dp[25][25][1010],cnt=-1,ans;
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
struct node{int x,y,k;};
bool ok(int j){
    if(nx==gx[j]&&ny<gy[j]){
        if(nx>tx)return true;
    }
    else if(tx==gx[j]&&ty<gy[j]){
        if(tx>nx)return true;
    }
    return false;
}
void bfs(){
    memset(dp,-1,sizeof(dp));
    queue<node> q;
    node u;u.x=sx;u.y=sy;u.k=0;q.push(u);dp[sx][sy][0]=0;
    while(!q.empty()){
        u=q.front();q.pop();nx=u.x;ny=u.y;int nk=u.k,tk;
        if(nx==sx&&ny==sy)ans=max(ans,w[nk]-dp[nx][ny][nk]);
        for(int i=0;i<4;i++){
            tx=nx+dx[i];ty=ny+dy[i];tk=nk;
            if(tx<1||tx>n||ty<1||ty>m||(map[tx][ty]!=‘.‘&&map[tx][ty]!=‘S‘))continue;
            for(int j=0;j<=cnt;j++)
                if(ok(j))tk^=(1<<j);
            if(dp[tx][ty][tk]==-1){
                dp[tx][ty][tk]=dp[nx][ny][nk]+1;
                node v;v.x=tx;v.y=ty;v.k=tk;q.push(v);
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",ch);
        for(int j=1;j<=m;j++){
            map[i][j]=ch[j-1];
            if(map[i][j]==‘S‘)sx=i,sy=j;
            if(map[i][j]>=‘1‘&&map[i][j]<=‘8‘){
                int t=map[i][j]-‘1‘;++cnt;
                gx[t]=i;gy[t]=j;
            }
        }
    }
    for(int i=0;i<=cnt;i++)scanf("%d",&val[i]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(map[i][j]==‘B‘){
                ++cnt;gx[cnt]=i;gy[cnt]=j;val[cnt]=-10000;
            }
    for(int i=0;i<(1<<cnt+1);i++)
        for(int j=0;j<=cnt;j++)
            if(i&(1<<j))w[i]+=val[j];
    bfs();
    printf("%d",ans);
    return 0;
}
时间: 2024-12-21 01:39:12

Circling Round Treasures(codeforces 375c)的相关文章

Codeforces Round #615(Div.3)解题报告

Codeforces Round #615(Div.3)解题报告 A. Collecting Coins 注意\(n\)可能不够用的情况. #include<bits/stdc++.h> using namespace std; typedef long long ll; int a, b, c, n; void solve() { cin >> a >> b >> c >> n; int mx = max(max(a, b), c); int

[题解]Yet Another Subarray Problem-DP 、思维(codeforces 1197D)

题目链接:https://codeforces.com/problemset/problem/1197/D 题意: 给你一个序列,求一个子序列 a[l]~a[r] 使得该子序列的 sum(l,r)-k*(r-l+1)/m(向上取整)的值是在所有子序列中最大的,并输出最大值 思路: 法一:动态规划 dp[i][j] 表示序列到i截止,这一轮已经进行了j次取数(j = (len+m-1)%m) 那么dp[i][j]维护的就是起点为 s = i-j+1-m*t (t>=0)这个集合的最优,这样所有的

AC自动机+dp(CodeForces - 86C )

"Multidimensional spaces are completely out of style these days, unlike genetics problems" — thought physicist Woll and changed his subject of study to bioinformatics. Analysing results of sequencing he faced the following problem concerning DNA

Palindrome Degree(CodeForces 7D)—— hash求回文

学了kmp之后又学了hash来搞字符串.这东西很巧妙,且听娓娓道来. 这题的题意是:一个字符串如果是回文的,那么k值加1,如果前一半的串也是回文,k值再加1,以此类推,算出其k值.打个比方abaaba,k值为3,abaxxaba,k值为1.现在,给出一个串,让你求这个串的所有前缀(包括本身)的k值的和. 如果考虑马拉车,那么先预处理出每个地方的最长回文长度,然后不断的截断,如果子串的回文长度大于其回文长度,那么k值加1,这样即可.但是马拉车写起来比较繁琐,没有模板我也没法手写. 这里提供hash

A - Playing with Paper (CodeForces - 527A)

- 题目大意 给定的矩形,每次裁剪最大的正方形,直到最后剩下正方形,总共有多少个正方形. - 解题思路 显然,每次裁剪后,原来的宽和(长-宽)变成了现在的长和宽,直到长等于宽. - 代码 #include<iostream> using namespace std; long long num(long long a, long long b) { if (b == 1) return a; if (a % b == 0) return a / b; return num(b, a % b)

Codeforces Round #626 (Div. 2) B. Count Subrectangles

题目连接:https://codeforces.com/contest/1323/problem/B 题意:给一个大小为n的a数组,一个大小为m的b数组,c数组是二维数组c[i][j]=a[i]*b[j],问面积为k的矩形有几个. 题解:先把k的所有因子存入一个数组里,然后遍历因子,表示在a数组有 i 个连续的1,那么如果在b数组里有 k/i 个连续的1,形成的矩形面积就是k(自己脑补一下吧),计算出a数组中符合条件的个数乘以b数组中符合条件的个数,然后把每个因子下的都加起来就是答案. 1 #i

Codeforces Round #423 (Div. 2)A B C D

A. Restaurant Tables 题意是一个点单人座有a个双人座有b个,有n组人,每组人有一个或两个人.当一个人时优先坐单人座的没有就坐没有人坐的双人座,然后才是在已经坐了一人的双人座,还没有就拒绝为他服务.当两个人时,只坐双人座的没有就拒绝服务.问这个店要拒绝服务多少人. 直接模拟下就行了. 1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 using namespace st

Educational Codeforces Round 63-D(基础DP)

题目链接:https://codeforces.com/contest/1155/problem/D 题意:给定n个数,可以选择一段连续子段将其乘x,也可以不操作,求最大连续子段和. 思路:比赛时觉得是dp,但怎么也想不出来QAQ,dp太难了...赛后看了别人题解,找到状态和转移方程就很简单了,然而比赛时我就是想不到... 考虑下标i:有3种情况,可能[0,i]都没有乘x,可能i乘了x,可能[i,n]都不会乘x.分别用dp[i][0]表示以i结尾的最长子段和且 [0,i]都没乘x,dp[i][1

BestCoder Round #41 -- (A,B)

题目传送:BestCoder Round #41 A.ZCC loves straight flush 思路:简单题,不过刚开始没看清题,wa了好几次,然后才发现输入不连续也可以,就是说每个同一花色的牌都可以放在一块,不用在意输入顺序,感觉这里题目应该说清楚点好些 AC代码(略挫,比赛时写的都比较乱): #include <cstdio> #include <cstring> #include <iostream> #include <algorithm>