题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1223
题意:有n个箱子,箱子有个承受炸弹的属性,比如箱子被x个炸弹一起炸不会坏但是被x+1个炸弹炸会坏掉,我们就说箱子承受能力E为x。现在我们知道箱子的E最大为m,但是不是确切地知道箱子的E值。现在给你n个箱子让你准确测出箱子的E值(每个箱子的E值相同,箱子一旦被炸掉就不能在再用了,但是没有被炸坏的话可以继续测试)。问在最坏情况下最少要用几个炸弹?
思路:f[x][L][R]表示用x个箱子准确测出[L,R]区间的E所用的最少炸弹,f[x][L][R]=min(i+max(f[x-1][L][i-1],f[x][i+1][R]))(L<=i<=R),即先测i个炸弹的,若箱子被炸坏,则为1+f[x-1][L][i-1],否则为1+f[x][i+1][R]。。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define max(x,y) ((x)>(y)?(x):(y)) 5 #define min(x,y) ((x)<(y)?(x):(y)) 6 using namespace std; 7 8 9 const int INF=1000000000; 10 int C,num=0; 11 int f[105][105][105],n,m; 12 13 14 int DFS(int x,int L,int R) 15 { 16 if(L>R) return 0; 17 int &ans=f[x][L][R],i; 18 if(ans!=-1) return ans; 19 ans=INF; 20 for(i=L;i<=R;i++) ans=min(ans,i+max(DFS(x-1,L,i-1),DFS(x,i+1,R))); 21 return ans; 22 } 23 24 void init() 25 { 26 memset(f,-1,sizeof(f)); 27 int i,j,k; 28 for(i=1;i<=100;i++) for(j=i;j<=100;j++) f[1][i][j]=(i+j)*(j-i+1)/2; 29 for(i=2;i<=100;i++) for(j=1;j<=100;j++) for(k=j;k<=100;k++) 30 DFS(i,j,k); 31 } 32 33 int main() 34 { 35 init(); 36 for(scanf("%d",&C);C--;) 37 { 38 scanf("%d%d",&m,&n); 39 printf("Case %d: %d\n",++num,f[m][1][n]); 40 } 41 return 0; 42 }