uva - 1379(无关状态不会被有用状态调用)

不会被调用到的状或者没有实际意义的状态,不会被调用到,就不会影响最终的结果,但在最终收集结果要避免它。

本题,看上去没有好办法,直接dp空间时间都受不了,可以先排序对阵每个对手的一行,则该行会被用到的会是前几个,但我不确定一定是前5个,但这样去做,就A了,有待证明。

本题有些特殊状态即前4天的状态,因为如第三天,在计算他的最优值是,只有他的前两天有参考价值,那么只参考前两个维度,d[ 3 ][  1 ] [  2 ] [  ] [  ]都是一个状态。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 110;
const int maxg = 240;
int dp[2][6][6][6][6],n,m,g,b[maxg];
#define rep(i,n) for(int i=0;i<n;i++)
int cmax(int& a,int b){
  if(a<b) a = b;
}
struct node{
 int v,id;
 node(int x=0,int y=0):v(x),id(y){}
 bool operator <(const node& rhs)const{
   return v>rhs.v;
 }
}a[110][maxn];
int main()
{
    for(int i=0;i<35;i++) a[i][0]=node(0,0);
    for(int i=0;i<100;i++) a[0][i]=node(0,0);
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d %d",&n,&m,&g);
        g+=10;
        for(int i=1;i<=m;i++){
          for(int j=1;j<=n;j++){
            scanf("%d",&a[i][j].v);
            a[i][j].id = j;
          }
          sort(a[i]+1,a[i]+1+n);
        }
        for(int i=1;i<=g;i++) scanf("%d",&b[i]);
        int pre = 0,now = 1;
        memset(dp,0,sizeof(dp));
        for(int i=g;i>=1;i--){
          memset(dp[now],0,sizeof(dp[now]));
          rep(j,6)
            rep(k,6)
              rep(l,6)
                rep(r,6){
                  int p = b[i];
                  if(!p) cmax(dp[now][j][k][l][r],dp[pre][0][j][k][l]);
                  else
                  for(int s=1;s<=5;s++){
                  if(a[p][s].id){
                     if(i-1>0&&a[p][s].id==a[b[i-1]][j].id) continue;
                     if(i-2>0&&a[p][s].id==a[b[i-2]][k].id) continue;
                     if(i-3>0&&a[p][s].id==a[b[i-3]][l].id) continue;
                     if(i-4>0&&a[p][s].id==a[b[i-4]][r].id) continue;
                  }
                  cmax(dp[now][j][k][l][r],dp[pre][s][j][k][l]+a[p][s].v);
                  }
                }
            pre^=1; now^=1;
        }
        int res = 0;
        rep(j,6)
            rep(k,6)
              rep(l,6)
                rep(r,6){
                  res = max(res,dp[pre][j][k][l][r]);
                }
       cout<<(res/(100.0))<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值