problem1 link

首先预处理在已选字母的状态为$state$时是否可达。

然后就是按照题目进行dp。设$f[i]$表示已选字母集合为$i$时的结果。

每次可以根据$i$中含有的字母是奇数还是偶数个来确定现在该轮到谁选择。

problem2 link

交点可以分为三部分:

(1)已经确定的线之间的交点;

(2)未确定的线之间的交点;

(3)已确定的线与未确定线之间的交点。

第一部分比较容易计算。

对于第二部分,设$f[i]$表示$i$对点之间连线交点期望。那么对于$f[i+1]$来说,就是在最后添加一对点,然后枚举这一对点中的一个与对面集合中那个点相连,可以得到:$f[i+1]=\frac{1}{i+1}\sum_{k=1}^{i+1}(f[i]+k-1)=f[i]+\frac{i}{2}$,进而可以直接计算出$f[n]$的通项公式。

对于第三部分,可以枚举下半部分每个未匹配的点与每条确定的点有交点的概率。

problem3 link

设宽高为$m,n$

将要连接的城市分别编号为0,1,2,3等,最多到7.规定$2k$到$2k+1$连接。

令$f[mask][x][y]$表示将$mask$代表的城市在点$(x,y)$处汇聚到一起的最小代价。

按照$mask$从小到大依次进行计算。令状态$p1,p2$满足$mask$^$p1=p2$且$p1!=mask,p2!=mask$

计算到$mask$时,一定计算完了$p1,p2$,此时可以先用$f[p1][x][y]+f[p2][x][y]$来更新$f[mask][x][y]$

然后从每个$f[mask][x][y]$开始进行bfs,来更新其他的$f[mask][x^{'}][y^{'}]$.

最后一个计算阶段。分别编号每一对要连接的城市为0,1,2,3(最多到3,即有四对)。令$dp[state]$表示将$state(<2^{4})$表示的城市对连接的最小代价,初始化为,比如$dp[(0010)_{2}]=min(f[(00001100)_{2}][x][y])$

对后对于每个$dp$的状态,用其子状态更新它。

code for problem1

import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class DoorsGame { static final int N = 1 << 16; int[] bitNum = new int[N]; boolean[] g1 = null;
boolean[] g2 = null; int[] f = new int[N]; int validMask = 0; public int determineOutcome(String doors, int trophy) {
for (int i = 1; i < N; ++ i) {
bitNum[i] = bitNum[i >> 1] + (i & 1);
}
String s1 = doors.substring(0, trophy);
String s2 = (new StringBuilder(doors.substring(trophy))).reverse().toString();
g1 = cal(s1);
g2 = cal(s2);
Arrays.fill(f, Integer.MAX_VALUE);
for (int i = 0; i < doors.length(); ++ i) {
validMask |= 1 << (doors.charAt(i) - 'A');
}
return dfs(0);
} int dfs(int mask) { if (g1[mask]) {
if (g2[mask]) {
return 0;
}
return bitNum[mask];
}
else {
if (g2[mask]) {
return -bitNum[mask];
}
}
if (f[mask] != Integer.MAX_VALUE) {
return f[mask];
} if (contains(bitNum[mask], 0)) {
for (int i = 0; i < 16; ++ i) {
if (!contains(mask, i) && contains(validMask, i)) {
int ans = dfs(mask | (1 << i));
if (f[mask] == Integer.MAX_VALUE) {
f[mask] = ans;
continue;
}
if (ans < 0) {
if (f[mask] >= 0 || f[mask] < ans) {
f[mask] = ans;
}
}
else if (ans == 0) {
if (f[mask] > 0) {
f[mask] = ans;
}
}
else {
if (f[mask] > 0 && f[mask] < ans) {
f[mask] = ans;
}
}
}
}
}
else {
for (int i = 0; i < 16; ++ i) {
if (!contains(mask, i)) {
int ans = dfs(mask | (1 << i));
if (f[mask] == Integer.MAX_VALUE) {
f[mask] = ans;
continue;
}
if (ans < 0) {
if (f[mask] < 0 && f[mask] > ans) {
f[mask] = ans;
}
}
else if (ans == 0) {
if (f[mask] < 0) {
f[mask] = ans;
}
}
else {
if (f[mask] <= 0 || f[mask] > ans) {
f[mask] = ans;
}
}
}
}
}
return f[mask];
} boolean[] cal(String s) {
boolean[] result = new boolean[N];
for (int i = 0; i < N; ++ i) {
int p = 0;
while (p < s.length()) {
if (contains(i, s.charAt(p) - 'A')) {
p += 1;
}
else {
break;
}
}
if (p == s.length()) {
result[i] = true;
}
}
return result;
} boolean contains(int mask, int t) {
return (mask & (1 << t)) != 0;
} }

 

code for problem2

import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class DrawingLines { public double countLineCrossings(int n, int[] startDot, int[] endDot) {
double result = 0; final int m = startDot.length;
for (int i = 0; i < m; ++ i) {
for (int j = i + 1; j < m; ++ j) {
boolean upper = startDot[i] < startDot[j];
boolean lower = endDot[i] < endDot[j];
if (upper != lower) {
result += 1;
}
}
}
result += (n - m) * (n - m - 1) / 4.0;
boolean[] b = new boolean[n + 1];
int[] pSum = new int[n + 1];
for (int i = 0; i < m; ++ i) {
b[endDot[i]] = true;
pSum[startDot[i]] = 1;
}
for (int i = 1; i <= n; ++ i) {
pSum[i] += pSum[i - 1];
}
if (n == m) {
return result;
}
for (int i = 1; i <= n; ++ i) {
if (b[i]) {
continue;
}
for (int j = 0; j < m; ++ j) {
if (endDot[j] < i) {
result += 1.0 * (startDot[j] - pSum[startDot[j]]) / (n - m);
}
else {
result += 1.0 * (n - startDot[j] - (m - pSum[startDot[j]])) / (n - m);
}
}
}
return result;
}
}

  

code for problem3

import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class BuildingRoads { int getCost(char c) {
if ('a' <= c && c <= 'z') {
return c - 'a' + 1;
}
if ('A' <= c && c <= 'Z') {
return (c - 'A' + 1) * 100;
}
if ('1' <= c && c <= '9') {
return (c - '0') * 10000;
}
if (c == '0') {
return 100000;
}
return 0;
} Map<Character,Integer> map = new HashMap<>(); int getIndex(Character c) {
if (c == '!' || c == '@' || c == '#' || c == '$') {
if (map.containsKey(c)) {
return map.get(c) + 1;
}
int s = map.size();
map.put(c, s * 2);
return s * 2;
}
return -1;
} int[][] g = null;
int n,m;
int[][][] f = null;
List<Integer> listx = new ArrayList<>();
List<Integer> listy = new ArrayList<>(); public int destroyRocks(String[] field) {
n = field.length;
m = field[0].length();
g = new int[n][m]; for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
g[i][j] = getCost(field[i].charAt(j));
int id = getIndex(field[i].charAt(j));
if (id != -1) {
while (listx.size() < id + 1) {
listx.add(0);
listy.add(0);
}
listx.set(id, i);
listy.set(id, j);
}
}
}
final int M = listx.size();
f = new int[1 << M][n][m];
for (int i = 0; i < (1 << M); ++ i) {
for (int j = 0; j < n; ++ j) {
Arrays.fill(f[i][j], -1);
}
}
for (int i = 0; i < M; ++ i) {
f[1 << i][listx.get(i)][listy.get(i)] = 0;
}
for (int i = 0; i < (1 << M); ++ i) {
update(i);
}
int[] dp = new int[1 << (M / 2)];
Arrays.fill(dp, -1);
for (int i = 0; i < dp.length; ++ i) {
int mask = 0;
for (int j = 0; j < M / 2; ++ j) {
if (contains(i, 1 << j)) {
mask |= 3 << (j * 2);
}
}
for (int x = 0; x < n; ++ x) {
for (int y = 0; y < m; ++ y) {
int t = f[mask][x][y] + g[x][y];
if (t != -1 && (dp[i] == -1 || dp[i] > t)) {
dp[i] = t;
}
}
}
}
for (int i = 0; i < dp.length; ++ i) {
for (int j = 0; j < i; ++ j) {
if (!contains(i, j)) {
continue;
}
if (dp[j] != -1 && dp[i ^ j] != -1) {
int t = dp[j] + dp[i ^ j];
if (dp[i] == -1 || dp[i] > t) {
dp[i] = t;
}
}
}
}
return dp[dp.length - 1];
} static class Node {
int cost;
int x;
int y; Node() {}
Node(int cost, int x, int y) {
this.cost = cost;
this.x = x;
this.y = y;
}
}
public static class NodeCompare implements Comparator<Node> {
@Override
public int compare(Node c1, Node c2) {
return c1.cost - c2.cost;
}
}; Queue<Node> queue = new PriorityQueue<>(new NodeCompare()); void upd(int x, int y, int cost, int mask) {
if (f[mask][x][y] == -1 || f[mask][x][y] > cost) {
f[mask][x][y] = cost;
queue.offer(new Node(cost, x, y));
}
} boolean contains(int x, int y) {
return (x & y) == y;
} int[] dx = {1, -1, 0, 0};
int[] dy = {0, 0, 1, -1}; void update(int mask) {
for (int i = 0; i < mask; ++ i) {
if (!contains(mask, i)) {
continue;
}
for (int x = 0; x < n; ++ x) {
for (int y = 0; y < m; ++ y) {
if (f[i][x][y] != -1 && f[mask ^ i][x][y] != -1) {
int t = f[i][x][y] + f[mask ^ i][x][y];
if (f[mask][x][y] == -1 || f[mask][x][y] > t) {
f[mask][x][y] = t;
}
}
}
}
}
while (!queue.isEmpty()) {
queue.poll();
}
for (int x = 0; x < n; ++ x) {
for (int y = 0; y < m; ++ y) {
if (f[mask][x][y] != -1) {
queue.add(new Node(f[mask][x][y], x, y));
}
}
}
while (!queue.isEmpty()) {
Node node = queue.poll();
int cost = node.cost;
int x = node.x;
int y = node.y;
if (f[mask][x][y] != cost) {
continue;
}
for (int i = 0; i < 4; ++ i) {
int xx = x + dx[i];
int yy = y + dy[i];
if (xx < 0 || xx >= n || yy < 0 || yy >= m) {
continue;
}
int newCost =cost;
if (g[x][y] != g[xx][yy]) {
newCost += g[x][y];
}
upd(xx, yy, newCost, mask);
}
}
}
}

  

topcoder srm 470 div1的更多相关文章

  1. Topcoder SRM 643 Div1 250<peter_pan>

    Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...

  2. Topcoder Srm 726 Div1 Hard

    Topcoder Srm 726 Div1 Hard 解题思路: 问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和. 然后可以证明一个结 ...

  3. topcoder srm 714 div1

    problem1 link 倒着想.每次添加一个右括号再添加一个左括号,直到还原.那么每次的右括号的选择范围为当前左括号后面的右括号减去后面已经使用的右括号. problem2 link 令$h(x) ...

  4. topcoder srm 738 div1 FindThePerfectTriangle(枚举)

    Problem Statement      You are given the ints perimeter and area. Your task is to find a triangle wi ...

  5. Topcoder SRM 602 div1题解

    打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...

  6. Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

    Problem Statement      The Happy Letter game is played as follows: At the beginning, several players ...

  7. Topcoder SRM 584 DIV1 600

    思路太繁琐了 ,实在不想解释了 代码: #include<iostream> #include<cstdio> #include<string> #include& ...

  8. TopCoder SRM 605 DIV1

    604的题解还没有写出来呢.先上605的. 代码去practice房间找. 说思路. A: 贪心,对于每个类型的正值求和,如果没有正值就取最大值,按着求出的值排序,枚举选多少个类型. B: 很明显是d ...

  9. topcoder srm 575 div1

    problem1 link 如果$k$是先手必胜那么$f(k)=1$否则$f(k)=0$ 通过对前面小的数字的计算可以发现:(1)$f(2k+1)=0$,(2)$f(2^{2k+1})=0$,(3)其 ...

随机推荐

  1. oracle 常用(一)

    常用的6个分组函数: 注意点:where字句中不能使用组函数.要用到having函数. 但是从优化角度看,尽量使用where avg :平均值           sum:求和            ...

  2. C# Dapper 简单实例

    /// <summary> /// 分页信息 /// </summary> public class PageInfo<T>     {         /// & ...

  3. 【转】HTTP429

    转载:http://codewa.com/question/45600.html Q:How to avoid HTTP error 429 (Too Many Requests) python Q: ...

  4. QString字符串中双引号的梗

    [1]QString字符串不支持双引号 最近做项目(本地环境:WIN10 + QT5.9.2 + VS2017).有个需求,需要实现形如 "key="123456"&qu ...

  5. 2017年3月29日 webService入门理解 二

    前边说到了N多webService的概念. 其实,说白了,我个人理解的话,webService就是一个“概念”.就好像互联网一样,就是一个很虚幻,很高的一个概念.同样,webService也是.互联网 ...

  6. AtCoder Beginner Contest 044 A - 高橋君とホテルイージー / Tak and Hotels (ABC Edit)

    Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement There is a hotel with ...

  7. SQL8数据库定期自动备份

    我们知道,利用SQL Server 2008数据库可以实现数据库的定期自动备份.方法是用SQL SERVER 2008自带的维护计划创建一个计划对数据库进行备份, 下面我们将SQL SERVER 20 ...

  8. 如何使用Linux 命令more 查看文本文件

    Linux 下有很多实用工具可以让你在终端界面查看文本文件.其中一个就是 more. more 跟我之前另一篇文章里写到的工具 —— less 很相似.它们之间的主要不同点在于 more 只允许你向前 ...

  9. vue 加载更多2

    <template lang="html"> <div class="yo-scroll" :class="{'down':(sta ...

  10. solr 使用指定数据源

    1,将solr 解压,我们观察发现它其实即可以是web服务也可以做数据分析 数据库 2,我们在example目录下新建一个hai的文件夹,用于存放数据 参考solr 目录,将solr.xml 复制一份 ...