NOI 97 (Vijos 1464)积木游戏(DP)
很普通的DP,设dp[i][j][k]为第i块积木放在第j堆且摆放状态为k的最高高度。方程很容易推出。
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi acos(-1.0) # define eps 1e-8 # define MOD 1000000007 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; int Scan() { int res=0, flag=0; char ch; if((ch=getchar())=='-') flag=1; else if(ch>='0'&&ch<='9') res=ch-'0'; while((ch=getchar())>='0'&&ch<='9') res=res*10+(ch-'0'); return flag?-res:res; } void Out(int a) { if(a<0) {putchar('-'); a=-a;} if(a>=10) Out(a/10); putchar(a%10+'0'); } const int N=105; //Code begin... int a[N][3], dp[N][N][3]; bool check(int i, int b, int j, int c) { int a1, a2, b1, b2; if (b==0) a1=1, a2=2; else if (b==1) a1=0, a2=2; else a1=0, a2=1; if (c==0) b1=1, b2=2; else if (c==1) b1=0, b2=2; else b1=0, b2=1; return (a[i][a1]<=a[j][b1]&&a[i][a2]<=a[j][b2])||(a[i][a2]<=a[j][b1]&&a[i][a1]<=a[j][b2]); } int main () { int n, m; scanf("%d%d",&n,&m); FOR(i,1,n) scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]); FOR(i,1,n) FOR(j,1,i) { int ma=0; FO(k,0,i) FO(l,0,3) ma=max(ma,dp[k][j-1][l]); FO(l,0,3) dp[i][j][l]=ma+a[i][l]; FO(k,j,i) FO(l1,0,3) FO(l2,0,3) if (check(i,l1,k,l2)) dp[i][j][l1]=max(dp[i][j][l1],dp[k][j][l2]+a[i][l1]); } int ans=0; FOR(i,m,n) FO(j,0,3) ans=max(ans,dp[i][m][j]); printf("%d\n",ans); return 0; }