您的位置:首页 > 其它

2013-5-12 训练赛后总结

2013-05-12 20:38 253 查看
感谢 谢大,duoxida,zhsl ,教会了我几个训练赛当中没有想出来的题。

A Force Brute

题意: 没发现其水题本质啊.. 给定 N个单词, 然后问最大循环次数.

解法: KMP next数组的运用, 更详细的可以看这一篇总结 /article/6522038.html

这里就简要说下, 因为求next的过程是一个一个构造循环节的, (L+1)-next[L+1] 即为当前字符串的最小循环节长度, 而 L%( (L+1)-next[L+1] ) 表示目前 循环节构造了多少个,若为0则意味着构造满了一个循环. 而 L / ( (L+1) - next[L+1] ) 表是目前已经构造了的循环节数量. 所以最终结果为

  令 d = (L+1) - next[L+1] , 则 ans = L/d + (L%d != 0)

若 next[L+1] = 1, 则代表整个串是 最小循环节. 其实发现可以不特殊处理的.

View Code

#include<cstdio>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;

const int N = 1010;

vector<int> Q[1010];

int g

, d

, dp

, a

;
int n, K;
int val
, v
, L
;
bool flag
;
int sum
;

int main(){
while( scanf("%d%d", &n,&K) != EOF){
memset(flag,0,sizeof(flag));
for(int i = 0; i <= n; i++) Q[i].clear();
for(int i = 1; i <= n; i++){
int p;
scanf("%d%d",&val[i],&p);
if( p != i ) Q[p].push_back(val[i]);
flag[p] = true;
}
memset(g,0,sizeof(g));
for(int x = 1; x <= n; x++){ // 第x件物品,其为主件
int len = (int)Q[x].size();
if( flag[x] ){
// 0,1 pack
memset(d,0,sizeof(d));
d[0][0] = val[x];
for(int i = 1; i <= len; i++){
for(int j = 0; j <= i; j++){
if( j == 0 ) d[i][j] = d[i-1][j];
else if( j == i ) d[i][j] = d[i-1][j-1] + Q[x][i-1];
else d[i][j] = max( d[i-1][j], d[i-1][j-1]+ Q[x][i-1] );
}
}
for(int i = 0; i <= len; i++)
g[x][i] = d[len][i];
}
}
int cnt = 0;
for(int i = 1; i <= n; i++){
if( flag[i] ){
L[++cnt] = Q[i].size();
for(int j = 0; j <= L[cnt]; j++)
a[cnt][j] = g[i][j];
}
}
memset( dp,0, sizeof(dp));
for(int i = 1; i <= cnt; i++){
for(int j = 0; j <= K; j++){
dp[i][j] = dp[i-1][j];
if( j > 0 ){
for(int k = 0; (k<=L[i]) && (k<j); k++){
dp[i][j] = max( dp[i][j], dp[i-1][j-(k+1)] + a[i][k] );
}
}
}
}
printf("%d\n", dp[cnt][K] );
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: