TopCoder SRM 667 Div.2题解

时间:2022-11-23 23:15:30

概览:

T1 枚举 T2 状压DP T3 DP


TopCoder SRM 667 Div.2 T1

解题思路

由于数据范围很小,所以直接枚举所有点,判断是否可行。时间复杂度O(δX × δY),空间复杂度O(1)。

参考程序段

#include <bits/stdc++.h>
using namespace std; class PointDistance {
public:
vector <int> findPoint( int x1, int y1, int x2, int y2 );
};
int sqr(int x){ return x * x; }
vector<int> ans;
vector <int> PointDistance::findPoint(int x1, int y1, int x2, int y2) {
ans.clear();
for(int x = -100; x <= 100; x++)
for(int y = -100; y <= 100; y++)
if(sqr(x1 - x) + sqr(y1 - y) > sqr(x2 - x) + sqr(y2 - y)){
ans.push_back(x);
ans.push_back(y);
return ans;
}
return ans;
}

TopCoder SRM 667 Div.2 T2

解题思路

可能大家的第一反应都是每一步选花费最小来贪心,但是发现,某一步有多个花费最小时,会出问题。

我们看一组数据

0000

1100

0011

0111

如果贪心, 可能顺序是1,2,3,4, 这样答案为8, 而事实上按顺序1,3,4,2,最优,为6。

于是我们考虑DP。

首先,我们令dp[i]表示在i的二进制表示下为1的那些指令处理完毕所需的最小花费。则可以从任何二进制表示下比i少一个1的j转移过来,我们取其最小。开始状态为dp[0] = 0,结束状态为dp[(1 << n) - 1]。

参考程序段

程序中,并非枚举dp[j]向dp[i]转移,而是对于dp[j]向每个可能的dp[i]转移,并使用了类似于spfa的写法。

同时,程序中q数组保存的数指向dp数组的下标,q_used对应花费。

#include <bits/stdc++.h>
using namespace std; class OrderOfOperationsDiv2 {
public:
int minTime( vector <string> s );
};
int n;
int rec[20];
int l, r, q[1 << 23], q_used[1 << 23];
int dp[1 << 21];
int len;
int OrderOfOperationsDiv2::minTime(vector <string> s) {
n = s.size();
len = s[0].size();
for(int i = 0; i < n; i++){
rec[i] = 0;
for(int j = 0; j < len; j++)
if(s[i][j] == '1') rec[i] |= (1 << j);//转成二进制方便处理
}
memset(dp, 255, sizeof(dp));
dp[0] = 0;
l = 0; r = 1; q[1] = 0; q_used[1] = 0;
while(l < r){
l++;
int rec_vis = q[l];
int rec_used = q_used[l];
for(int i = 0; i < n; i++){//枚举可能被更新的状态
if((rec_vis >> i) & 1) continue;
int x = rec_vis | (1 << i);
int y = rec_used | rec[i];
int tt = 0;
for(int j = 0; j < len; j++)
if(((y >> j) & 1) == 1 && ((rec_used >> j) & 1) == 0) tt++;
tt = tt * tt;
if(dp[x] == -1 || dp[x] > dp[rec_vis] + tt){
dp[x] = dp[rec_vis] + tt;
r++;
q[r] = x;
q_used[r] = y;
}
}
}
return dp[(1 << n) - 1];
}

TopCoder SRM 667 Div.2 T3

解题思路

乍一看好像很麻烦呐。看起来有后效性?仿佛不能用dp?唉?然而数据只有30?所以考虑以下乱搞?

emmm

我们还是dp,大不了扩大维数,增加状态数。嗯。我们令dp[i][j][k]表示前i幢楼,在第i幢楼这里开了j家店,同时计划在下一幢楼开k家能获得的利益。那么我们可以得到状态方程

\[dp[i][j][k] = max(dp[i][j][k], dp[i - 1][l][j] + j * c[i * 3 * m + (j + k + l) - 1])(0 <= l <= m)
\]

特判一下第一栋楼和最后一栋楼。

同时注意下小细节

1、题目里并没有给出c[-1]的定义,所以任意相邻三栋楼中一定要开一家:)

2、只有一栋楼的情况:)

时间复杂度O(n^4), 空间复杂度O(n^3)【这个我觉得还是叫暴力比较好:捂脸:】

参考代码段

#include <bits/stdc++.h>
using namespace std; class ShopPositions {
public:
int maxProfit( int n, int m, vector <int> c );
};
int f[40][40][40];
int ShopPositions::maxProfit(int n, int m, vector <int> c) {
memset(f, 0, sizeof(f));
int ans = 0;
for(int j = 0; j <= m; j++)//特判第一栋楼
for(int k = 0; k <= m; k++){
if(j + k == 0) continue;
f[0][j][k] = max(f[0][j][k], j * c[0 * 3 * m + (j + k) - 1]);
ans = max(ans, f[0][j][k]);
}
for(int i = 1; i < n - 1; i++)
for(int j = 0; j <= m; j++)
for(int k = 0; k <= m; k++)//O(n^4)DP
for(int l = 0; l <= m; l++){
if(j + k + l == 0) continue;
f[i][j][k] = max(f[i][j][k], f[i - 1][l][j] + j * c[i * 3 * m + (j + k + l) - 1]);
ans = max(ans, f[i][j][k]);
}
if(n > 1)//如果不止一栋楼,就特判最后一栋楼
for(int j = 0; j <= m; j++)
for(int l = 0; l <= m; l++){
if(j + l == 0) continue;
f[n - 1][j][0] = max(f[n - 1][j][0], f[n - 2][l][j] + j * c[(n - 1) * 3 * m + (j + l) - 1]);
ans = max(ans, f[n - 1][j][0]);
}
return ans;
}

TopCoder SRM 667 Div.2题解的更多相关文章

  1. Topcoder SRM 674 Div&period;2题解

    T1 解题思路 这题应该不是很难,主要是题意理解问题. 注意给出的两个数组里映射关系已经对应好了,只要判断是否为双射即可 参考程序 #include <bits/stdc++.h> usi ...

  2. TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization &amp&semi; Codeforces 839 E

    传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相 ...

  3. &lbrack;topcoder&rsqb;SRM 633 DIV 2

    第一题,http://community.topcoder.com/stat?c=problem_statement&pm=13462&rd=16076 模拟就可以了. #includ ...

  4. TopCoder SRM 596 DIV 1 250

    body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } P ...

  5. &lbrack;topcoder&rsqb;SRM 646 DIV 2

    第一题:K等于1或者2,非常简单.略.K更多的情况,http://www.cnblogs.com/lautsie/p/4242975.html,值得思考. 第二题:http://www.cnblogs ...

  6. 【topcoder SRM 702 DIV 2 250】TestTaking

    Problem Statement Recently, Alice had to take a test. The test consisted of a sequence of true/false ...

  7. Topcoder SRM 656 &lpar;Div&period;1&rpar; 250 RandomPancakeStack - 概率&plus;记忆化搜索

    最近连续三次TC爆零了,,,我的心好痛. 不知怎么想的,这题把题意理解成,第一次选择j,第二次选择i后,只能从1~i-1.i+1~j找,其实还可以从j+1~n中找,只要没有被选中过就行... [题意] ...

  8. Topcoder SRM 648 &lpar;div&period;2&rpar;

    第一次做TC全部通过,截图纪念一下. 终于蓝了一次,也是TC上第一次变成蓝名,下次就要做Div.1了,希望div1不要挂零..._(:зゝ∠)_ A. KitayutaMart2 万年不变的水题. # ...

  9. Topcoder SRM 145 DIV 1

    Bonuses 模拟 题意:给你一个序列,按照百分比排序,再将百分比取整,再把剩余百分比加到最大的那几个. 题解:按照题意模拟就好.

随机推荐

  1. 解决secureCRT数据库里没有找到防火墙 &&num;39&semi;无&&num;39&semi;问题

    中文版的secureCRT由于汉化的问题(把null翻译成无了),导致每次打开都会有个防火墙的错误提示:数据库里没有找到防火墙 '无' 此会话将尝试不通过防火墙进行连接.出现这个错误的原因是在secu ...

  2. Communication - 03&period;RILC

    RIL层的作用大体上就是将上层的命令转换成相应的AT指令,控制modem工作.生产modem的厂家有很多:Qualcomm, STE, Infineon... 不同的厂家都有各自的特点,当然也会有各自 ...

  3. js时间字符串转Date对象

    var DATE_REGEXP = new RegExp("(\\d{4})-(\\d{2})-(\\d{2})([T\\s](\\d{2}):(\\d{2}):(\\d{2})(\\.(\ ...

  4. Labview学习之波形图表的历史数据

    Labview学习之波形图表的历史数据 默认的情况下,波形图表显示100个点, 因为波形图表默认的缓冲区大小为1024,在默认的情况下如果修改图形图标属性中的标尺项,选中自动调整标尺,如图:2011- ...

  5. STM32驱动DHT11温湿度传感器

    DHT11 是一款湿温度一体化的数字传感器.该传感器包括一个电阻式测湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接.通过单片机等微处理器简单的电路连接就能够 实时的采集本地湿度和温 ...

  6. input 的 oninput onkeypress onkeydown onchange 事件的区别

    事件执行顺序: <input type="text" id="foo" onkeydown="console.log('down')" ...

  7. 报错android&period;view&period;InflateException&colon; Binary XML file line &num;11&colon; Attempt to invoke virtual method &&num;39&semi;boolean

    出现这种问题,打开Android monitor的调试信息发现是 android.view.InflateException: Binary XML file line #11: Attempt to ...

  8. 铺砖问题 (状态压缩dp)

    问题描述: 给定m×n个格子,每个格子被染成了黑色或白色.现在要用1×2的砖块覆盖这些格子,要求快于快之间互相不重叠,且覆盖了所有白色的格子(用 . 表示),但不覆盖任意一个黑色的格子(用 x 表示) ...

  9. linux应用之wget命令详解

    wget是linux最常用的下载命令, 一般的使用方法是: wget + 空格 + 要下载文件的url路径 例如: # wget linuxsense.org/xxxx/xxx.tar.gz&quot ...

  10. IT兄弟连 Java语法教程 变量2

    变量的作用域和生命周期 到目前为止,使用的所有变量都是在main()方法开始时声明的,然而,Java允许在任何代码块(代码块以开花括号开始,以闭花括号结束)中声明变量,代码块定义了作用域.因此,每当开 ...