UVA - 10934 Dropping water balloons(思维+dp)

传送门


很神奇的一道题,看起来是求最小的实验次数,实际上程序主体并没有用到 m i n min min,而是递推解决问题,先看下LRJ的思路:设 d [ i ] [ j ] d[i][j] d[i][j]用i个气球实验j次所能测试楼的最高层数,第一次决策,设测试楼层为 k k k

  • 如果气球破了,说明前 k − 1 k-1 k1层必须能用 i − 1 i-1 i1个球实验 j − 1 j-1 j1次测出来,也就是说 k = d [ i − 1 ] [ j − 1 ] + 1 k=d[i-1][j-1]+1 k=d[i1][j1]+1是最优

  • 如果气球没破,则相当于把第k+1层楼看作1楼以后的继续。因此在k层楼之上还可以测试 d [ i ] [ j − 1 ] d[i][j-1] d[i][j1]层楼,即 d [ i ] [ j ] = k + d [ i ] [ j − 1 ] = d [ i − 1 ] [ j − 1 ] + d [ i ] [ j − 1 ] d[i][j]=k+d[i][j-1]=d[i-1][j-1]+d[i][j-1] d[i][j]=k+d[i][j1]=d[i1][j1]+d[i][j1]

但是为什么这么想呢?我们实际要求的是一个最大的范围,对应着最小的试验次数。如果它破了,说明硬度小于 k k k,那么你还剩下 i − 1 i-1 i1个气球和 j − 1 j-1 j1次实验,必须能够确定出 1 − ( k − 1 ) 1-(k-1) 1(k1)的硬度范围,即 d ( i − 1 , j − 1 ) ≥ k − 1 d(i-1,j-1) \geq k-1 d(i1,j1)k1,换句话说,我们选择的 k k k不能太大,须有 k < = d ( i − 1 , j − 1 ) + 1 k<=d(i-1,j-1)+1 k<=d(i1,j1)+1。如果在第 k k k层没破,说明硬度大于等于 k k k,还剩下 i i i个气球和 j − 1 j-1 j1次实验,为了尽可能地扩大可确定的范围,我们应当把第 k + 1 k+1 k+1层当作第1层,使用 d ( i , j − 1 ) d(i,j-1) d(i,j1)的方法测量以上楼层,这是最优的,这样所能确定的最大范围是 [ 1 , a ] + d ( i , j − 1 ) [1,a]+d(i,j-1) [1,a]+d(i,j1),即 d ( i , j ) = m a x ( k + d ( i , j − 1 ) ) = d ( i − 1 , j − 1 ) + d ( i , j − 1 ) + 1 d(i,j)=max(k+d(i,j-1))=d(i-1,j-1)+d(i,j-1)+1 d(i,j)=max(k+d(i,j1))=d(i1,j1)+d(i,j1)+1

reference:简书kinoud

说道这里还是有一点似懂非懂,慢慢领会吧,下面还有一个讲的更好的文章:

Click Here

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <cstdio>
#include <string>
#include <bitset>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> P;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=105;

ll d[maxn][maxn];
ll n,k;

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    //ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	for(int i=1;i<=maxn;i++)
		for(int j=1;j<=63;j++)
			d[i][j]=d[i-1][j-1]+d[i][j-1]+1;
    while(~scanf("%lld%lld",&k,&n) && k){
        int ans=-1;
		for(int i=1;i<=63;i++)
			if(d[k][i]>=n){
				ans=i;
				break;
			}
		if(ans<0) printf("More than 63 trials needed.\n");
		else printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(UVA - 10934 Dropping water balloons(思维+dp))