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. 《shell下sort排序命令的使用》

    首先建立一个文件,很乱,没有规律: 正排序: 倒排序: Uniq 删除文件中的重复行:用此命令要先对文件进行排序. 对文件冗余,只要文件所有重复的字符显示一次: 显示1-7,不重复的行: 只显示1-7 ...

  2. 《DNS的正向反向解析》RHEL6

    DNS的正向解析: Iptables –F Setenforce 0 安装DNS服务器的软件包: 启动DNS服务器: 修改DNS的配置文件:vim /etc/named.conf 修改DNS的配置:( ...

  3. IE8浏览器跨域接口访问异常的解决办法

    IE8版本以下浏览器绝对是一个神奇的存在,忙碌好久,万事具备,居然在ajax调用接口的时候直接爆炸 陈述一下问题 首先是有这样一个接口,请求类型POST,入参JSON,出参JSON,jQuery aj ...

  4. 为Eclipse设置背景色

    1:打开Eclipse,在菜单栏找到Help—>Install new software.. 2:在打开的Work with中输入: Update Site - http://eclipse-c ...

  5. 通过数据绑定模板得到对应的Item控件

    这类控件都继承于Selector,其中主要有ComboBox.listview.listbox.datagrid. 由于个人对WPF的了解所有可能有遗漏,希望各位能够指出一起进步. 在遍历上面控件时主 ...

  6. WPF学习笔记 控件篇 属性整理【1】FrameworkElement

    最近在做WPF方面的内容,由于好多属性不太了解,经常想当然的设置,经常出现自己未意料的问题,所以感觉得梳理下. ps:先补下常用控件的类结构,免得乱了 .NET Framework 4.5 Using ...

  7. linux c 验证登录密码

    #define _XOPEN_SOURCE #include <stdio.h> #include <unistd.h> int main(int argc, char *ar ...

  8. IO流的异常处理

    在IO流的异常处理时应该注意以下几点: 1.在外边建立引用,在Try内进行初始化(FileWriter fw = null;) 2.文件的路径使用必须是双斜杠,转义(fw = new FileWrit ...

  9. WCF-Configuration

    Host-Configuration <?xml version="1.0"?> <configuration> <configSections> ...

  10. Andriod wifi 基本操作

    从用户角度看,Android Wi-Fi模块自下向上可以看为5层:硬件驱动程序,wpa_suppplicant,JNI,WiFi API,WifiSettings应用程序. 1.wpa_supplic ...