http://codeforces.com/contest/6/problem/D

题目大意:有一队人,排成一列,每个人都有生命值,你每次可以攻击2~n位置的一个的人,假设每次攻击的位置为pos,那么pos位受到a点伤害,pos-1和pos+1受到b点伤害。问让所有人生命值都小于0所需要的最少操作数。

思路:最近在加强dp类型的题目,但是因为做过一点IDA*,感觉这题貌似可以用IDA*差不多的思路来做哈?(关键是我不会DP,TAT)然后我们找寻一下IDA*的可行性剪枝就好了:目前数列的maxval<=(lim - deep) * a即可,否则TLE了

这是IDA*的代码

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = ;
const int inf = 0x3f3f3f3f;
int road[maxn * maxn];
int n, a, b;
int h[maxn]; bool dfs(int pos, int deep, int lim){ int maxcnt = -inf;
for (int i = ; i <= n; i++) maxcnt = max(maxcnt, h[i]);
if (deep > lim) return false;
if (maxcnt > (lim - deep) * a) return false;//加上这个剪枝就变得超快
if (deep == lim){
if (maxcnt >= )return false;
else return true;
}
if (pos == n) return false; int cnt = max(h[pos - ] / b, max(h[pos] / a, h[pos + ] / b)) + ;
for (int cnt1 = ; cnt1 <= cnt; cnt1++){
if (h[pos - ] >= cnt1 * b) continue;
h[pos - ] -= b * cnt1; h[pos] -= a * cnt1; h[pos + ] -= b * cnt1;
for (int j = deep + ; j <= deep + cnt1; j++)
road[j] = pos;
if (dfs(pos + , deep + cnt1, lim)) {
for (int j = deep + ; j <= deep + cnt1; j++) road[j] = pos;
return true;
}
h[pos - ] += b * cnt1; h[pos] += a * cnt1; h[pos + ] += b * cnt1;
}
return false;
} int main(){
memset(road, , sizeof(road));
cin >> n >> a >> b;
int beg = ;
for (int i = ; i <= n; i++) scanf("%d", h + i);
for (int i = ; i <= * ; i++)
if (dfs(, , i)){
printf("%d\n", i);
for (int j = ; j <= i; j++)
printf("%d%c", road[j], j == i ? '\n' : ' ');
break;
}
return ;
}

明天附上DP代码。晚安~

dp思路:

定义dp[i][j][k][z]表示目前攻击第i个人,j表示第i-1个人的生命,k表示第i个人的生命,z表示第i+1个人的生命。然后转移需要注意一下以下方面

①简单的转移:dp[i][j - b][k - a][z - b] = dp[i][j][k][z];

②如果j-b以后的生命值为0了,那么dp[i+1][k - a][z - b][h[i + 2]]=dp[i][j][k][z] + 1;

③如果j本来就为0,那么dp[i+1][k][z][h[i + 2]] = dp[i][j][k][z];

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = ;
const int inf = 0x3f3f3f3f;
struct Point{
int i, j, k, z;
Point(int i = , int j = , int k = , int z = ): i(i), j(j), k(k), z(z){}
}par[maxn][maxn][maxn][maxn];
int dp[maxn][maxn][maxn][maxn];
int n, a, b;
int h[maxn]; int main(){
cin >> n >> a >> b;
for (int i = ; i <= n; i++){
scanf("%d", h + i); h[i]++;
}
memset(par, -, sizeof(par));
memset(dp, 0x3f, sizeof(dp));
dp[][h[]][h[]][h[]] = ;
for (int i = ; i <= n - ; i++){
for (int j = h[i - ]; j >= ; j--){
for (int k = h[i]; k >= ; k--){
for (int z = h[i + ]; z >= ; z--){
int nj = max(, j - b), nk = max(, k - a), nz = max(, z - b);
if (dp[i][nj][nk][nz] > dp[i][j][k][z] + ){
dp[i][nj][nk][nz] = dp[i][j][k][z] + ;
par[i][nj][nk][nz] = Point(i, j, k, z);
}
if (nj == && dp[i + ][nk][nz][h[i + ]] > dp[i][j][k][z] + ){
dp[i + ][nk][nz][h[i + ]] = dp[i][j][k][z] + ;
par[i + ][nk][nz][h[i + ]] = Point(i, j, k, z);
}
if (j == && dp[i + ][k][z][h[i + ]] > dp[i][j][k][z]){
dp[i + ][k][z][h[i + ]] = dp[i][j][k][z];
par[i + ][k][z][h[i + ]] = par[i][j][k][z];
}
}
}
}
}
int ans = dp[n][][][];
printf("%d\n", ans);
Point tmp = Point(n, , , );
while (ans--){
tmp = par[tmp.i][tmp.j][tmp.k][tmp.z];
printf("%d ", tmp.i);
}
return ;
}

四维dp 或者 剪枝 + dfs Codeforces Beta Round #6 (Div. 2 Only) D的更多相关文章

  1. 暴力/DP Codeforces Beta Round #22 (Div. 2 Only) B. Bargaining Table

    题目传送门 /* 题意:求最大矩形(全0)的面积 暴力/dp:每对一个0查看它左下的最大矩形面积,更新ans 注意:是字符串,没用空格,好事多磨,WA了多少次才发现:( 详细解释:http://www ...

  2. Codeforces Beta Round #83 (Div. 1 Only)题解【ABCD】

    Codeforces Beta Round #83 (Div. 1 Only) A. Dorm Water Supply 题意 给你一个n点m边的图,保证每个点的入度和出度最多为1 如果这个点入度为0 ...

  3. Codeforces Beta Round #77 (Div. 2 Only)

    Codeforces Beta Round #77 (Div. 2 Only) http://codeforces.com/contest/96 A #include<bits/stdc++.h ...

  4. Codeforces Beta Round #65 (Div. 2)

    Codeforces Beta Round #65 (Div. 2) http://codeforces.com/contest/71 A #include<bits/stdc++.h> ...

  5. Codeforces Beta Round #59 (Div. 2)

    Codeforces Beta Round #59 (Div. 2) http://codeforces.com/contest/63 A #include<bits/stdc++.h> ...

  6. Codeforces Beta Round #52 (Div. 2)

    Codeforces Beta Round #52 (Div. 2) http://codeforces.com/contest/56 A #include<bits/stdc++.h> ...

  7. Codeforces Beta Round #40 (Div. 2)

    Codeforces Beta Round #40 (Div. 2) http://codeforces.com/contest/41 A #include<bits/stdc++.h> ...

  8. Codeforces Beta Round #22 (Div. 2 Only)

    Codeforces Beta Round #22 (Div. 2 Only) http://codeforces.com/contest/22 A 水题 #include<bits/stdc+ ...

  9. Codeforces Beta Round #14 (Div. 2)

    Codeforces Beta Round #14 (Div. 2) http://codeforces.com/contest/14 A 找最大最小的行列值即可 #include<bits/s ...

随机推荐

  1. ios打开系统自带APP

    打开系统自带app 打开系统设置: [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root= ...

  2. linux环境vnc部署过程详解

    vnc服务端机器地址:10.165.38.68 vnc客户端机器地址:本机(windows机器) vnc客户端包:vnc_82537_82537.rar (百度云盘下载地址:http://pan.ba ...

  3. Python读取ini配置文件

    db_config.ini [baseconf] host=127.0.0.1 port=3306 user=root password=root db_name=evaluting_sys [con ...

  4. 第五十六节,python实现支持并发、断点续传的Ftp程序

    一.要求 1.用户md5认证 2.支持多用户同时登陆(并发) 3.进入用户的命令行模式,支持cd切换目录,ls查看目录子文件 4.执行命令(ipconfig) 5.传输文件: a.支持断点续传 b.传 ...

  5. iOS开发加快审核app

    实现app加快审核的步骤: 1.https://developer.apple.com/contact/进入这个网址点击App Store下的Expediting an App Review进入这个页 ...

  6. 【解题报告】瑞士轮(NOIP2011普及组T3)

    [题外话:这道题吧……说实话我不太喜欢……因为卡快排.] 题目不贴了,就是给你一个赛制,然后各个选手的初始得分和能力值,问你进行R轮比赛之后第Q名的编号是多少(这个编号读进来就要算OYZ,初始快排的时 ...

  7. 如何理解CSS中的浮动 :其实他就像乘坐扶梯一样

    只要你用过自动扶梯,你就能很快的理解CSS中的浮动(Float). 你肯定遇到过这样的情况:       做好了,你想用CSS浮动来调整元素间的位置关系. 在写完代码之后,你发现浮动元素没出现在你设想 ...

  8. FZU 2086 餐厅点餐

     好久不写博客了……得有快一个月了……看到大神们一篇篇博文 唉……差好多……这一个月 有蓝桥杯还有校赛……校赛签到题都没签完 实力铁牌……不过蓝桥杯一等奖 五月份帝都之行还挺令人期待……清明小长假之前 ...

  9. Chapter 15_1 require函数

    Lua提供了一个名为require的高层函数来加载模块,但这个函数只假设了关于模块的基本概念. 对于require而言,一个模块就是一段定义了一些值(函数或者包含函数的table)的代码. 为了加载一 ...

  10. NOIP2005-普及组复赛-第二题-校门外的树

    题目描述 Description 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0 ...