题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3069
题目大意:有两个人,他们在某一天各要依次用一些物品,每种物品只有一个,也就是相同的物品不能在同一个时间段用,每个人用每个物品都有一个时间,问你怎么安排,使他们都用完的时间最小,然后输出这个最小时间。
思路:很明显的DP,设两个为p、q, i、j 这两个维是很明显的,由于要记录时间差,所以还要增加一维表示p的时刻 - q的时刻,设d[ i ][ j ][ k ] ,表示 p 的前 i 个物品, q 的前 j 物品,p - q 的时刻差为k,这里还有一个限制,就是 k 这一部分只能是某个单件物品产生的(这个是纯属我看着别人AC代码的个人理解,。 = =),然后就是画图分类讨论了,由于比较烦,这里就不一一列举了,具体看代码吧。。
自己想的时候,3个状态倒是很容易想,然后我竟然转移的是d[ i - 1][ j - 1],因为当时就觉得应该两个一起讨论,SB了,这样只会 1、1,2、2这样下去。。 其实是i、j - 1 和 i - 1、j 。。。= =
看了一眼别人代码,忽然才发现的,可就是有一点不好处理,也就是我上面说的那个个人理解,我感觉状态定义为这样,可以解释得通。。 就先这样理解吧,如果有哪位神牛路过,希望能指点一二。
ZOJ也有一道这个题目,可是就是ZOJ能过,LA上WA了。。 不知道为什么。。难道ZOJ数据水了。。。 看了大家都做得是ZOJ,好吧,ZOJ过了就好了吧。。还有就算不是WA,应该也是TLE,因为LA上是3S,而ZOJ有10S,而我的要跑4S+,汗,所以上面给的也是ZOJ 题目的网址。。。想不出有什么可以优化的方法,还请各路神牛赐教。。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 0x0fffffff;
int d[303][303][202];
int t_p[303],t_q[303];
int p[303],q[303];
int main()
{
int _;
scanf("%d",&_);
while(_--)
{
int n;
scanf("%d",&n);
for(int i = 1;i<=n;i++)
scanf("%d",&t_p[i]);
for(int i = 1;i <= n;i ++)
scanf("%d",&t_q[i]);
int len_p,len_q;
scanf("%d%d",&len_p,&len_q);
p[0] = q[0] = 0;
for(int i = 1;i <= len_p;i++)
scanf("%d",&p[i]);
for(int i = 1;i <= len_q;i ++)
scanf("%d",&q[i]);
int pos = 100;
for(int i = 0;i <= len_p; i ++)
for(int j = 0;j <= len_q; j++)
for(int k = -100 ;k <= 100 ;k++)
d[i][j][k+pos] = INF;
d[0][0][0 + pos] = 0;
for(int i = 0;i <= len_p; i++)
for(int j = 0;j <= len_q ;j++)
{
for(int k = -100;k<=100;k++)
{
if(d[i][j][k + pos] >= INF) continue;
if(j < len_q && p[i] == q[j +1])
{
if(k >= 0)
{
d[i][j+1][-t_q[q[j+1]] + pos] = min(d[i][j][k + pos] + t_q[q[j+1]],d[i][j+1][-t_q[q[j+1]] + pos]);
}
else
{
d[i][j+1][-t_q[q[j+1]] + pos] = min(d[i][j][k + pos] + t_q[q[j+1]],d[i][j+1][-t_q[q[j+1]] + pos]);
}
}
else if(j < len_q)
{
if(k >= 0)
d[i][j+1][k - t_q[q[j+1]] + pos] = min(d[i][j][k + pos] + max(0,-k + t_q[q[j+1]]),d[i][j+1][k - t_q[q[j+1]] + pos]);
else
d[i][j+1][-t_q[q[j+1]] + pos] = min(d[i][j][k + pos] + t_q[q[j+1]],d[i][j+1][-t_q[q[j+1]] + pos]);
}
if(i < len_p && p[i+1] == q[j])
{
if(k >= 0)
d[i+1][j][t_p[p[i+1]] + pos] = min(d[i][j][k + pos] + t_p[p[i+1]],d[i+1][j][t_p[p[i+1]] + pos]);
else
d[i+1][j][t_p[p[i+1]] + pos] = min(d[i][j][k +pos] + t_p[p[i+1]],d[i+1][j][t_p[p[i+1]] + pos]);
}
else if(i < len_p)
{
if(k >= 0)
d[i+1][j][t_p[p[i+1]] + pos] = min(d[i][j][k + pos] + t_p[p[i+1]],d[i+1][j][t_p[p[i+1]] + pos]);
else
d[i+1][j][k + t_p[p[i+1]] + pos] = min(d[i][j][k + pos] + max(0,k + t_p[p[i+1]]),d[i+1][j][k + t_p[p[i+1]] + pos]);
}
}
}
/*for(int i = 0;i<=len_p;i++)
for(int j = 0;j <= len_q ;j++)
for(int k = -100;k<=100;k++)
if(d[i][j][k+pos] < INF)
{
printf("i = %d,j = %d,k = %d,d = %d\n",i,j,k,d[i][j][k+pos]);
}*/
int ans =INF;
for(int k = -100;k<=100;k++)
ans = min(ans,d[len_p][len_q][k+pos]);
printf("%d\n",ans);
}
return 0;
}
/*
3
2
1 2
2 1
2 2
1 2
1 2
*/