TC SRM 605
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的更多相关文章
- TC srm 673 300 div1
TC srm.673 300 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 Description 给你n(n<=50)匹马和n个人,一匹马和一个人能 ...
- TC SRM 597 DEV2
第一次玩TC的SRM,只完成了一题,有点失落,不过还是要把每个问题都研究清楚才是我的本性,呵呵 第一题思路: 任意一个数,不断除掉2以后的剩下的数若相同则YES否则NO 第二题: 最开始判断字母个数是 ...
- TopCoder SRM 605 DIV1
604的题解还没有写出来呢.先上605的. 代码去practice房间找. 说思路. A: 贪心,对于每个类型的正值求和,如果没有正值就取最大值,按着求出的值排序,枚举选多少个类型. B: 很明显是d ...
- TC SRM 663 div2 B AABB 逆推
AABB Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description One day, Jamie noticed that many En ...
- TC SRM 663 div2 A ChessFloor 暴力
ChessFloor Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description Samantha is renovating a squa ...
- TC SRM 665 DIV2 A LuckyXor 暴力
LuckyXorTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description A lucky number is a positive int ...
- Topcoder SRM 605 div1 题解
日常打卡- Easy(250pts): 题目大意:你有n种汉堡包(统统吃掉-),每一种汉堡包有一个type值和一个taste值,你现在要吃掉若干个汉堡包,使得它们taste的总和*(不同的type值的 ...
- TC SRM 593 DIV1 250
我只能说的亏没做,要不就挂0了.. 本来想四色定理,肯定4就可以的...然后准备爆,发现3的时候不好爆,又想了老一会,嗯,数据范围不小,应该不是暴力,直接找规律,貌似最大就是3,有一个3连块,输出3, ...
- TC SRM 593 DIV2 1000
很棒的DP,不过没想出,看题解了..思维很重要. #include <iostream> #include <cstdio> #include <cstring> ...
随机推荐
- hadoop2.2.0伪分布式搭建
1.准备Linux环境 1.0点击VMware快捷方式,右键打开文件所在位置 -> 双击vmnetcfg.exe -> VMnet1 host-only ->修改subnet ...
- CentOS 6.4 升级 Mysq5.5l方法 和 用户远程登录数据库
一:.在这里我们都知道 系统的yum源Mysql版本一般都是5.1 5.2的比较多 但是有些程序 必须要5.5以上的版本才能支持 这时候我们应该怎么办呢 编译安装也太慢 太费时间 那么我们就必要要 ...
- JS input文本框禁用右键和复制粘贴功能的代码
代码如下: function click(e) { if (document.all) { ||||) { oncontextmenu='return false'; } } if (document ...
- RHEL7 添加用户,含sudo权限
1.添加普通用户[root@server ~]# useradd book //添加一个名为book的用户 [root@server ~]# passwd book //修改密码 Changing p ...
- 用golang启动一个daemon
用golang启动一个daemon package main import ( "fmt" "log" "os" "runtime ...
- 通过js获取DropDownList的选中项
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...
- jquery 在ie10中post数据,最终数据丢失的BUG修复
最近在做项目的时候,发现ie10或者360之类套壳的浏览器(ie10) 在jquery调用post数据的时候,真实的请求并没有上传数据,原因不表,请见 http://stackoverflow.com ...
- 连续子数组的最大和/1007. Maximum Subsequence Sum (25)
题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量 ...
- Microsoft Azure Preview portal 以及Preview Features介绍
首先mooncake版本并不提供此类功能. 国际版会把将来推出的功能提供Preview,而且是免费的,有想研究未来技术以及的同学可以尝试 通过以下地址进入国际版,往下拉 http://azure.mi ...
- ASP.NET对HTML元素进行权限控制(三)
上一篇博客中有些没有考虑到的东西这次更改一下代码如下: 界面前台: <%@ Page Language="C#" AutoEventWireup="true&quo ...