zoj 3554 A Miser Boss
题意:有a、b、c三个人同时工作,三个人做不同的任务需要不同的时间,但最后要求三个人做事情的总时间相同,输出做完所有任务需要的最少时间,如果无法达到三个人总工作时间相同,则输出“No”
当时一股脑筋觉着是最大流或者其他图论的东西,然后也往dp上想过,就连状态表示都没想出来。后来借鉴了一下大牛们的做法,标准做法应该是bfs所有可能情况,然后再一一帅选。这个bfs好久没写过了,暂时就没写。
还有一种特别巧妙的方法:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 250 //maxn设为250是保证250>=120*2
#define see(x) cout<<#x<<":"<<x<<endl;
short dp[41][maxn][maxn];
void adjust(short &x, short y){
if(x==-1||x>y){
x = y;
}
}
int main(){
int n, a, b, c;
int i, j, k, l;
while(~scanf("%d",&n)){
memset(dp,-1,sizeof(dp));
dp[0][121][121] = 0; //把初始值设置在121处,是一个很巧的方法
//平时一般都喜欢吧初始值设置在0、1处,但是此题,有加有减,121是一个减去120后大于0,加上120后小于maxn的数
for(i=0;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
// see(i)
for(j=0;j<maxn;j++){
for(k=0;k<maxn;k++){
if(dp[i][j][k]>=0){ //本来以为可以不用了,觉得反正有一个0,所以其他的-1 不用忽略也行
//后来发现如果不加的话会相当混乱,难以保证最后的结果是由以赋初值的dp[0][121][121]得来的,而且-1<0 有木有!!!
if(j+a<maxn){
adjust(dp[i+1][j+a][k],dp[i][j][k]+a);
}
if(j-b>=0&&k+b<maxn){
adjust(dp[i+1][j-b][k+b],dp[i][j][k]+b);
}
if(k-c>=0){
adjust(dp[i+1][j][k-c],dp[i][j][k]+c);
}
}
}
}
//see(dp[i+1][121][121])
}
if(dp[n][121][121]==-1){
printf("NO\n");
}
else{
printf("%d\n",dp[n][121][121]/3);
}
}
return 0;
}