POJ1179
POJ1179
区间DP
很简单的思考过程,把所有的东西看成一个圆,枚举去掉每一个边的情况。然后每一种都是一条链的区间DP。
l == r : dp[l][r] = num[l];
l != r : dp[l][r] = max(dp[l+1][r],dp[l][r-1]);
但是需要注意的是,这题有一个天坑,就是
负数乘负数可以变成一个大的正数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <deque>
#include <bitset>
using namespace std;
#define lowbit(x) x&-x
#define ll long long
#define dob double
#define For(i,s,n) for(ll i = s;i <= n;i++)
#define mem0(a) memset(a,0,sizeof a)
#define gcd(a,b) __gcd(a,b)
const int N = 5e2+600;
const double eps = 1e-6;
const ll mod = 1e9+7;
const int inf = 0x3f3f3f3f;
int n;
int num[N],a[N];
char fac[N];
int dp1[N][N],dp2[N][N];
bool vis[N][N] = {false};
void dfs(int l,int r){
if(vis[l][r]) return;
vis[l][r] = true;
if(l == r) {
dp1[l][r] = dp2[l][r] = num[l];
return ;
}
For(k,l,r-1){
if(fac[k+1] == 't'){
dfs(l,k);dfs(k+1,r);
dp1[l][r] = max(dp1[l][r],dp1[l][k]+dp1[k+1][r]);
dp2[l][r] = min(dp2[l][r],dp2[l][k]+dp2[k+1][r]);
}
else{
dfs(l,k);dfs(k+1,r);
dp1[l][r] = max(dp1[l][r],dp1[l][k]*dp1[k+1][r]);
dp1[l][r] = max(dp1[l][r],dp1[l][k]*dp2[k+1][r]);
dp1[l][r] = max(dp1[l][r],dp2[l][k]*dp1[k+1][r]);
dp1[l][r] = max(dp1[l][r],dp2[l][k]*dp2[k+1][r]);
dp2[l][r] = min(dp2[l][r],dp1[l][k]*dp1[k+1][r]);
dp2[l][r] = min(dp2[l][r],dp1[l][k]*dp2[k+1][r]);
dp2[l][r] = min(dp2[l][r],dp2[l][k]*dp1[k+1][r]);
dp2[l][r] = min(dp2[l][r],dp2[l][k]*dp2[k+1][r]);
}
}
return ;
}
int main() {
ios::sync_with_stdio(false);
cout.tie(NULL);
cin>>n;
For(i,1,2*n)
For(j,1,2*n)
dp1[i][j] = -inf,dp2[i][j] = inf;
For(i,1,n) {
cin>>fac[i]>>num[i];
num[i+n] = num[i],fac[i+n] = fac[i];
}
int ans = -inf;
For(i,1,n){
dfs(i,i+n-1);
ans = max(ans,dp1[i][i+n-1]);
}
cout<<ans<<endl;
int ok = 0;
For(i,1,n){
if(ans == dp1[i][i+n-1]){
if(ok) cout<<' ';
cout<<i;
ok = 1;
}
}
return 0;
}