昨天真是SB,20多个人花了6个小时顶着太阳去爬山,结果为了赶车还没到顶,真心不如在机房打代码。
题目链接:HZAUoj 1015: LCS
题意:给定两个字符串a和b,让你找它们特殊的LCS——该LCS在a、b原串中任一连续段长度不小于k。问你最长的LCS。
思路:考虑
dp
设置
End[i][j]
表示以a[i]、b[j]结尾的串的最大连续段长度。
设置
dp[i][j]
表示a[1] - a[i]串 和 b[1] - b[j]串的 最优特殊LCS。
那么转移
if(End[i][j]>=k)dp[i][j]=max(dp[i−p][j−p]+p);(k<=p<=End[i][j])
elsedp[i][j]=max(dp[i−1][j],dp[i][j−1]);
但是这样转移是O(n^3)会T。
发现对于第一个转移来讲,只有两种情况(1) 不拆开以a[i]、b[j]结尾的最大连续子串;(2) 拆开,肯定拆到a[i-k]、b[j-k]是最优的。
那么转移就可以变到O(1)了。这样时间复杂度O(n^2)。
dp[i][j]=max(dp[i−k][j−k]+k,dp[i−End[i][j]][j−End[i][j]]+End[i][j]);
AC代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <stack>
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 3 * 1e6 + 10;
const int MOD = 9973;
const int INF = 0x3f3f3f3f;
int End[2200][2200], start[2200][2200];
int dp[2200][2200];
char a[2200], b[2200];
int main()
{
int k;
while(scanf("%s%s", a+1, b+1) != EOF) {
scanf("%d", &k);
int la = strlen(a+1), lb = strlen(b+1);
End[0][0] = 0;
for(int i = 1; i <= la; i++) {
for(int j = 1; j <= lb; j++) {
if(a[i] == b[j]) {
End[i][j] = End[i-1][j-1] + 1;
}
else {
End[i][j] = 0;
}
dp[i][j] = 0;
}
}
for(int i = 1; i <= la; i++) {
for(int j = 1; j <= lb; j++) {
if(End[i][j] >= k) {
dp[i][j] = max(dp[i - k][j - k] + k, dp[i - End[i][j]][j - End[i][j]] + End[i][j]);
}
else {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
printf("%d\n", dp[la][lb]);
}
return 0;
}
题目链接:HZAUoj 1016: Array C 【贪心】
题意:分别给定n个数a[]和b[]。现在可以选择改变a[](只能减小,最小为0),且要保证 ∑ni=1a[i]>=m 。问你最小的 ∑ni=1a[i]∗a[i]∗b[i]
思路:显然,最后的 ∑ni=1a[i]==m 才是最优的。那么只要考虑将a[]的和减少到m就可以了,怎么减少呢?肯定先选择对整体贡献最大的减小。考虑第i个数对整体的贡献为 a[i]∗a[i]∗b[i] ,当 a[i] 减一时有 (a[i]−1)∗(a[i]−1)∗b[i] ,第一个减第二个就是减少 a[i] 的代价,我们肯定选择代价最大的先减。那么用个优先队列维护就好了。
AC代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <stack>
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 3 * 1e6 + 10;
const int MOD = 9973;
const int INF = 0x3f3f3f3f;
struct Node {
int id, cost;
friend bool operator < (Node a, Node b) {
return a.cost < b.cost;
}
};
int a[1010], b[1010];
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF) {
int sum = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum += a[i];
}
int sub = sum - m;
priority_queue<Node> Q; Node now;
for(int i = 1; i <= n; i++) {
scanf("%d", &b[i]);
now.id = i; now.cost = (2 * a[i] - 1) * b[i];
Q.push(now);
}
LL ans = 0;
while(sub--) {
now = Q.top(); Q.pop(); a[now.id]--;
now.cost = (2 * a[now.id] - 1) * b[now.id];
Q.push(now);
}
for(int i = 1; i <= n; i++) {
ans += a[i] * a[i] * b[i];
}
printf("%lld\n", ans);
}
return 0;
}