Div2  AlienAndSetDiv2   1000 pts

题意:1~2N的数分成2个数组A,B,并且数组中按增序排列,同时满足|A[i] - B[i]| <= K,问有多少种方法?

分析:从大到小依次决定每个数的放置位置,每次可以放在A或B中剩余的较高位置,当决定第i个数时,i+K+1,应该是已经匹配了,

那么只剩下i+1~i+K最多K个数处于未匹配的位置,用一个整数st表示,那么对于第i个数的转移情况,可以放置在某个数组中,

使他处于未匹配状况或者让他匹配.

dp[i][st]表示i个数需要划分,且i+1~i+K+1的未匹配情况用st的表示的方案数.

代码:

 const int MOD = (int)1e9 + ;
const int maxn = *;
const int maxm = (<<) + ;
int dp[maxn][maxm]; class AlienAndSetDiv2{
public:
int K, N, M;
int dfs(int n, int st) {
int &res = dp[n][st];
if (res != -) return res;
res = ;
if (st&(<<(K-))) {
res = dfs(n-, (st<<) % M);
} else {
if (st == ) {
res = dfs(n-, );
} else {
res = dfs(n-, st<<|);
int highBit = K-;
while (!((<<highBit) & st)) highBit--;
res = (res + dfs(n-, (st^(<<highBit))<<)) % MOD;
}
}
if (st == ) res = res*%MOD;
return res;
}
int getNumber(int N, int K) {
memset(dp, -, sizeof dp);
dp[][] = ;
for (int i = ; i < maxm; i++) dp[][i] = ;
M = (<<K);
this->K = K;
this->N = N; return dfs(*N, );
}
};

Div1 AlienAndHamburgers  250pts

题意:n种物品,每种物品有两个值taste[i],type[i]分别表示其美味值和类型,要求从中选出一些物品,使得类型数*美味值总和最大.

分析: 按类型排序,将类型相同的物品安排在连续一段考虑,对于第i个物品,如果选中,需要考虑前面一个选中的物品j, 及之前选中的类型总数,

如果j的类型和i的类型不同,那么选中前一个物品j的时候,选中的类型数比当前少1;否则就和当前类型数目一样.

设立状态表示dp[i][x][y] 表示选中第i的时候,选中的类型为x,选择的类型数为y的最大值.

代码:

 typedef long long LL;
typedef unsigned US;
typedef pair<int, int> PII;
typedef map<PII, int> MPS;
typedef MPS::iterator IT;
const int maxn = ;
int dp[maxn][maxn][maxn];
int vis[];
bool mark[maxn][maxn][maxn];
int cnt;
struct Node {
int val, t;
Node() {}
Node (int val, int t) {
if (!vis[t]) {
vis[t] = ++cnt;
}
this->t = vis[t];
this->val = val;
}
bool operator < (const Node &o) const {
return t < o.t;
}
} a[maxn];
class AlienAndHamburgers {
public:
int n;
int dfs(int pos, int x, int y) {
int &res = dp[pos][x][y];
if (mark[pos][x][y]) return res;
mark[pos][x][y] = true;
res = -inf;
if (x == || y == ) return res;
for (int i = ; i < pos; i++) {
int nx = a[i].t;
int ny = y - !(nx == x);
int z = dfs(i, nx, ny);
if (res < (z == -inf ? 1LL * -inf : (ny == ? 1LL * y * a[pos].val : (0LL + z / ny + a[pos].val) * y)))
res = (z == -inf ? 1LL * -inf : (ny == ? 1LL * y * a[pos].val : (0LL + z / ny + a[pos].val) * y));
}
return res;
} int getNumber(vector <int> type, vector <int> taste) {
// memset(dp, -1, sizeof dp);
memset(mark, false, sizeof mark); cnt = ;
for (int i = ; i < maxn; i++) {
for (int j = ; j < maxn; j++) {
for (int k = ; k < maxn; k++)
dp[k][i][j] = -inf;
mark[][i][j] = true;
}
}
dp[][][] = ; memset(vis, , sizeof vis); n = (int)type.size(); for (int i = ; i < n; i++) {
a[i + ] = Node(taste[i], type[i]);
}
a[].t = a[].val = ;
sort(a + , a + n + );
int ans = ;
for (int i = ; i <= n; i++)
for (int j = ; j <= a[i].t; j++)
ans = max(ans, dfs(i, a[i].t, j));
return ans;
}
};

Div1 AlienAndSetDiv1    450pts

题意:Div2 1000pts升级版,不同的是题目条件|A[i]-B[i]| <= K 变成了|A[i]-B[i]| >= K.不过分析过程还是差不多的.

分析:同样的从2N 到1按照从大到小的顺序进行安排,从A,B的高位往下进行放置.由于两个数要相差K以上才能配对,因此当考虑第i个数的时候,

对于尚未配对且满足>=i+K的数此时是可以和剩下的任意数配对的,而i+1~i+K-1之间的数时需要继续等待的,因此此时状态表示变成了dp[i][st][j],表示

分配剩下的i个数时,>=i+K的个数有j个,i+1~i+K-1之间的状态是st,这样只需要建立状态转移即可.

代码:

 const int maxn =  + ;
const int maxm = ( << ) + ;
const int MOD = ; int dp[maxn][maxn][maxm]; class AlienAndSetDiv1 {
public:
int N, K, M;
int dfs(int n, int m, int st) {
int &res = dp[n][m][st];
if (res != -) return res;
res = ;
if (K == ) {
res = dfs(n - , m + , );
if (m > )
res = (res + dfs(n - , m - , )) % MOD;
} else {
if (st == ) {
if (m == ) {
res = dfs(n - , K == , K != );
} else {
res = dfs(n - , m - , );
res = (res + dfs(n - , m + (K == ), K != )) % MOD;
}
} else {
if (m == ) {
res = dfs(n - , ((st & ( << (K - ))) != ) + (K == ), (st << | (K != )) % M); } else {
res = dfs(n - , m - + ((st & ( << (K - ))) != ), (st << ) % M);
res = (res + dfs(n - , m + (K == ) + ((st & ( << (K - ))) != ), (st << | (K != )) % M)) % MOD;
}
}
}
if (st == && m == ) res = res * % MOD;
return res;
}
int getNumber(int N, int K) {
memset(dp, -, sizeof dp);
for (int i = ; i < maxn; i++)
for (int j = ; j < maxm; j++)
dp[][i][j] = ;
dp[][][] = ;
M = << (K - );
this->N = N;
this->K = K;
return dfs( * N, , );
}
};

Div1 AlienAndPermutation 1000pts

题意:给定一个数组P为1~N数字的排列,最多可以进行K次操作:每次选取一个区间,将区间中的数替换成该区间内的数的最大值,最后能够得到不同的数组S.

分析:要解决这个题目首先要发现操作后的数组的性质,

1. S中满足S[j] = P[i]的位置构成连续序列

2. P[i]和P[j]的连续序列在S中相对位置不变

3. P[i]在S中的连续序列l~r满足对于任意处于l~r范围内的jP[j] <= Pi]

4. 对于操作后的序列S,有多少不同的值则需要多少次操作,这其中应该除开长度为1,且i = j的那些元素构成的序列.

下面设立状态表示f(i, j, k, d)表示已经决定P中前i个元素在S中的位置,S中前j个位置已经被占领,剩下k次操作的方案数,当然每个P[i]值最多算做一次操作,用一维d记录是否已经消耗了操作.

j = n 时,res = 1

否则如果i = n,res = 0.

其他情况:

如果S[j]不等于P[i]的值,转移到f(i+1, j, k, 0);否则

对于d = 1 or i == j,转移到f(i, j+1, k, d), 否则f(i, j+1, k-1, 1).

代码:

 typedef long long LL;
typedef unsigned US;
typedef pair<int, int> PII;
typedef map<PII, int> MPS;
typedef MPS::iterator IT;
const int MOD = ;
const int maxn = ;
int dp[maxn][maxn][maxn][];
int l[maxn], r[maxn]; class AlienAndPermutation{
public:
int n, K;
int dfs(int x, int y, int k, int d) {
int &res = dp[x][y][k][d];
if (res != -) return res;
if (y == n) return res = ;
if (x == n) return res = ;
res = ;
res = dfs(x+, y, k, );
if (l[x] <= y && y <= r[x]) {
if (d == || x == y)
res = (res + dfs(x, y+, k, d)) % MOD;
else if (k > ) res = (res + dfs(x, y+, k-, )) % MOD;
}
return res;
}
int getNumber(vector <int> P, int K) {
n = (int)P.size();
this->K = K;
memset(dp, -, sizeof dp);
for (int i = ; i < n; i++) {
l[i] = r[i] = i;
while (l[i] - >= && P[l[i]-] <= P[i]) l[i]--;
while (r[i]+ < n && P[r[i]+] <= P[i]) r[i]++;
}
return dfs(, , K, );
}
};

代码:

TC SRM 605的更多相关文章

  1. TC srm 673 300 div1

    TC srm.673 300 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 Description 给你n(n<=50)匹马和n个人,一匹马和一个人能 ...

  2. TC SRM 597 DEV2

    第一次玩TC的SRM,只完成了一题,有点失落,不过还是要把每个问题都研究清楚才是我的本性,呵呵 第一题思路: 任意一个数,不断除掉2以后的剩下的数若相同则YES否则NO 第二题: 最开始判断字母个数是 ...

  3. TopCoder SRM 605 DIV1

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

  4. TC SRM 663 div2 B AABB 逆推

    AABB Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description One day, Jamie noticed that many En ...

  5. TC SRM 663 div2 A ChessFloor 暴力

    ChessFloor Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description Samantha is renovating a squa ...

  6. TC SRM 665 DIV2 A LuckyXor 暴力

    LuckyXorTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description A lucky number is a positive int ...

  7. Topcoder SRM 605 div1 题解

    日常打卡- Easy(250pts): 题目大意:你有n种汉堡包(统统吃掉-),每一种汉堡包有一个type值和一个taste值,你现在要吃掉若干个汉堡包,使得它们taste的总和*(不同的type值的 ...

  8. TC SRM 593 DIV1 250

    我只能说的亏没做,要不就挂0了.. 本来想四色定理,肯定4就可以的...然后准备爆,发现3的时候不好爆,又想了老一会,嗯,数据范围不小,应该不是暴力,直接找规律,貌似最大就是3,有一个3连块,输出3, ...

  9. TC SRM 593 DIV2 1000

    很棒的DP,不过没想出,看题解了..思维很重要. #include <iostream> #include <cstdio> #include <cstring> ...

随机推荐

  1. Java抽象类和抽象方法例子

    题目:定义Shape类表示一般二维图形.Shape具有抽象方法area和perimeter,分别计算形状的面积和周长.试定义一些二维形状类(如矩形.三角形.圆形等),这些均为Shape类的子类并计算出 ...

  2. php 判断字符串在另一个字符串中位置

    $email='user@example.com';        //定义字符串$result=strstr($email,'@');         //返回子字符串echo $result; / ...

  3. 【面试虐菜】—— LVS负载均衡

    Load Balancer(负载均衡器): Load Balancer是整个集群系统的前端,负责把客户请求转发到Real Server上.Load Balancer通过Ldirectord监测各Rea ...

  4. 升级 CentOS git 1.7.1 到 1.7.12

    CentOS 源里的 git 版本是 1.7.1,如果远程创建的库所用 git 的版本比它高,在 pull 的时候,如果本地有修改,就会永久阻塞:在 push 的时候就会失败. CentOS 源里的 ...

  5. IOS键盘样式风格有关设置

    一.键盘风格 UIKit框架支持8种风格键盘. typedef  enum  { UIKeyboardTypeDefault,                 // 默认键盘:支持所有字符 UIKey ...

  6. (菜鸟要飞系列)一,基于Asp.Net MVC5的后台管理系统(前言)

    今天真是个郁闷的日子,因为老师两个星期前给我的一个任务,用递归算法将Oracle数据库中用户信息及权限显示在jquery-treeView上,网上虽然有大神写出了这类算法,但是不贴全部代码,真的很难跟 ...

  7. 使用JAXP进行sax解析

    package cn.liuning.sax; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactor ...

  8. python学习小结6:模块

    模块:在Python中有一个概念叫做模块(module),简单地说,模块就是一个保存了Python代码的文件.          模块能定义函数,类和变量,模块里也能包含可执行的代码.         ...

  9. DB天气app冲刺二阶段第五天

    昨天什么事情也没做..看了一场哆啦a梦 所以就不算冲刺了.. 今天主要就是做了一下需要用到的图片的整理还有的就是UI主界面需要展示用的素材,发现好多东西都需要搜索半天,虽然这个不是什么技术活..但真的 ...

  10. Document.defaultView

    Document.defaultView 引子 最近愚安在写一个可以将页面上的资源链接转为二维码以方便移动端浏览的chrome插件,由于dom操作并不多,而且作为插件不需要考虑跨 浏览器兼容性,所以并 ...