Atribuição de tarefas (dp)
Descrição
Existem n tarefas a serem concluídas por A e B. Cada tarefa é concluída por A ou B, e o tempo necessário é ai e bi, respectivamente. Pergunte quanto tempo levará para concluir todas as tarefas, pelo menos.
Entrada
Um número inteiro positivo nn na primeira linha indica que há n tarefas.
Em seguida, existem n linhas, cada uma com dois inteiros positivos ai e bi.
Resultado
Um número, o tempo mínimo de que precisam para concluir todas as tarefas.
Amostras
Entrada
3
5 10
6 11
7 12
Resultado
12
Dica
[Explicação das amostras de entrada e saída]
A conclui a tarefa 1 e a tarefa 2 e o tempo é 11. B conclui a tarefa 3 às 12h.
Ou A conclui a tarefa 1 e a tarefa 3, o tempo é 12. B conclui a tarefa 2 no tempo 11.
[Limites]
30% dos dados atendem: 1≤n≤20
100% dos dados atendem: 1≤n≤200, 1≤ai, bi≤200
Ideias:
Dp tridimensional é melhor empurrar, mas o tempo e o espaço não permitem isso.
A solução positiva é um estado dp bastante estranho.
dp [i] [j] significa completar as primeiras i tarefas, e o tempo gasto por A é j;
O valor de dp [i] [j] representa o tempo que leva para B completar as primeiras i tarefas.
A divisão é baseada em se a i-ésima tarefa é concluída por A ou B.
Código:
const int maxn=210;
int dp[maxn][maxn*maxn];
int a[maxn],b[maxn],n;
void solve(){
n=read();
for(int i=1;i<=n;i++){
a[i]=read(),b[i]=read();
}
memset(dp,0x3f,sizeof dp);
dp[0][0]=0;
int sum=0;
for(int i=1;i<=n;i++){
sum=sum+a[i];
for(int j=0;j<=sum;j++){
dp[i][j]=dp[i-1][j]+b[i];//b完成第i个任务
if(j>=a[i]) dp[i][j]=min(dp[i][j],dp[i-1][j-a[i]]);//a完成第i个任务
}
}
int res=0x3f3f3f3f;
for(int i=0;i<=sum;i++)///可能需要的时间
res=min(res,max(i,dp[n][i]));///注意取的先后顺序
cout<<res<<endl;
}