D题很恶心的要用大数。
dp[i] 表示到第 i 条信息的最大收益。
显然,dp[1] = 0。
对于i > 1有,若当前信息为 win x,那么显然有dp[i] = dp[i-1]。
若当前信息为sell x,那么dp[i] = max(dp[i-1] , dp[j] + 2^x),j 需满足j < i && 第j条信息为 win y && y == x。
import java.util.Scanner;
import java.math.BigInteger;
import java.io.*;
public class Main
{
public static void main(String[] args)
{
Scanner cin = new Scanner(System.in);
String []op = new String[5010];
int []val = new int[5010];
BigInteger []dp = new BigInteger[5010];
int i,j,n;
n = cin.nextInt();
BigInteger TWO = BigInteger.valueOf(2);
for(i = 1;i <= n; ++i)
{
op[i] = cin.next();
val[i] = cin.nextInt();
}
dp[1] = BigInteger.ZERO;
for(i = 2;i <= n; ++i)
{
dp[i] = dp[i-1];
if(op[i].length() == 4)
{
for(j = i-1;j >= 1; --j)
{
if(val[i] == val[j] && op[j].length() == 3)
{
dp[i] = dp[i].max(dp[j].add(TWO.pow(val[j])));
}
}
}
}
System.out.println(dp[n]);
}
}
E题让我见识了CF服务器的强大。2*10^8的算法才跑了900+。
思路:
因为相邻块颜色不同且每行有且只有两种颜色,所以每行的格式必为ABABABA。
所以我们预处理出val[i][A][B]所需花费。i为行,A,B分别表示此行用这两种颜色。o(n*(m+26*26)。
然后为o(n*26^4)的枚举,详见代码。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <ctime>
#include <iomanip>
#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-6)
#define _LL long long
#define ULL unsigned long long
#define LL __int64
#define INF 0x3f3f3f3f
#define Mod 1000000007
/** I/O Accelerator Interface .. **/
#define g (c=getchar())
#define d isdigit(g)
#define p x=x*10+c-'0'
#define n x=x*10+'0'-c
#define pp l/=10,p
#define nn l/=10,n
template<class T> inline T& RD(T &x)
{
char c;
while(!d);
x=c-'0';
while(d)p;
return x;
}
template<class T> inline T& RDD(T &x)
{
char c;
while(g,c!='-'&&!isdigit(c));
if (c=='-')
{
x='0'-g;
while(d)n;
}
else
{
x=c-'0';
while(d)p;
}
return x;
}
inline double& RF(double &x) //scanf("%lf", &x);
{
char c;
while(g,c!='-'&&c!='.'&&!isdigit(c));
if(c=='-')if(g=='.')
{
x=0;
double l=1;
while(d)nn;
x*=l;
}
else
{
x='0'-c;
while(d)n;
if(c=='.')
{
double l=1;
while(d)nn;
x*=l;
}
}
else if(c=='.')
{
x=0;
double l=1;
while(d)pp;
x*=l;
}
else
{
x=c-'0';
while(d)p;
if(c=='.')
{
double l=1;
while(d)pp;
x*=l;
}
}
return x;
}
#undef nn
#undef pp
#undef n
#undef p
#undef d
#undef g
using namespace std;
char Map[510][510];
int ans[2][26];
int val[510][26][26];
int pre[510][26][26][2];
void dfs(int n,int m,int px,int py)
{
if(n == 1)
{
for(int i = 1; i <= m; ++i)
if(i&1)
printf("%c",(char)(px+'a'));
else
printf("%c",(char)(py+'a'));
puts("");
return ;
}
dfs(n-1,m,pre[n][px][py][0],pre[n][px][py][1]);
for(int i = 1; i <= m; ++i)
if(i&1)
printf("%c",(char)(px+'a'));
else
printf("%c",(char)(py+'a'));
puts("");
}
int main()
{
int n,m,i,j,k,l,p;
scanf("%d %d",&n,&m);
for(i = 1; i <= n; ++i)
scanf("%s",Map[i]+1);
for(i = 1; i <= n; ++i)
{
memset(ans,0,sizeof(ans));
for(j = 1; j <= m; ++j)
ans[j&1][Map[i][j]-'a']++;
for(j = 0; j < 26; ++j)
for(k = 0; k < 26; ++k)
val[i][j][k] = m-ans[1][j]-ans[0][k];
}
int Min;
for(i = 2; i <= n; ++i)
{
for(j = 0; j < 26; ++j)
for(k = 0; k < 26; ++k)
{
Min = INF;
for(l = 0; l < 26; ++l)
{
if(j == l)
continue;
for(p = 0; p < 26; ++p)
{
if(k == p || l == p)
continue;
if(val[i-1][l][p] < Min)
Min = val[i-1][l][p],pre[i][j][k][0] = l,pre[i][j][k][1] = p;
}
}
val[i][j][k] += Min;
}
}
Min = INF;
int px,py;
for(i = 0; i < 26; ++i)
for(j = 0; j < 26; ++j)
if(i != j && val[n][i][j] < Min)
Min = val[n][i][j],px = i,py = j;
printf("%d\n",Min);
dfs(n,m,px,py);
return 0;
}