[dp & greedy] UVA1228 integer transmission

Greedy 1: First of all, it can be specified that all 0s and 1s in k (number to be received) are received in the original order, that is, each number will not be received earlier than the similar number before it in k, because in each such case, can be adjusted to receive in the original order, so the deletion of the number obtained in this case has no effect on the answer

For example, in the above figure, if you adjust the receiving order of two 0s, you will find that the maximum time delay of the two numbers will become smaller, making it easier to meet the conditions

Greedy 2: Whenever you need to receive a 0 or 1, you must receive the leftmost one in k that has not been received, because this number must be received sooner or later, and it is easy to exceed the time limit for later reception.

So dp is dp[i][j], which means receiving i 0s and j 1s from left to right from k, which can form several numbers. There are two decisions to receive 0 and 1 each time. But this is bound to produce many illegal decisions. The judgment method is that if a 0 is currently to be received, the leftmost unreceived 1 plus the position where d is less than this 0, then this 1 cannot be received in the future, so this decision is invalid. If it is equal, you can receive the 1 at the same time as the 0, and arrange the 1 after the 0 received at the same time.

Another detail is to use ull, ll will explode

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL unsigned long long
using namespace std;
int n,d,m1,m0,A[200],T[200][200];
LL k,dp[200][200];
LL get_max(){
	int i,j;
	LL k=0;
	memset(T,0,sizeof(T));
	for (i=1;i<=n;i++)
		if (A[i]) T[i][1]++;
		else T[i+d][0]++;
	for (i=1;i<=n+d;i++){
		for (j=1;j<=T[i][1];j++) k<<=1,k++;
		for (j=1;j<=T[i][0];j++) k<<=1;
	}
	return k;
}
LL get_min(){
	int i,j;
	LL k=0;
	memset(T,0,sizeof(T));
	for (i=1;i<=n;i++)
		if (!A[i]) T[i][0]++;
		else T[i+d][1]++;
	for (i=1;i<=n+d;i++){
		for (j=1;j<=T[i][0];j++) k<<=1;
		for (j=1;j<=T[i][1];j++) k<<=1,k++;
	}
	return k;
}
LL DP(){
	memset(dp,0,sizeof(dp));
	memset(T,0,sizeof(T));
	m1=0; m0=0;
	int i,j;
	for (i=1;i<=n;i++)
		if (A[i]) T[1][++m1]=i;
		else T[0][++m0]=i;
	dp[0][0]=1;
	for (i=0;i<=m0;i++)
		for (j=0;j<=m1;j++){
			if (i<m0&&(j==m1||T[1][j+1]+d>=T[0][i+1])) dp[i+1][j]+=dp[i][j];
			if (j<m1&&(i==m0||T[0][i+1]+d>=T[1][j+1])) dp[i][j+1]+=dp[i][j];
		}
	return dp[m0][m1];
}
int main(){
	int cnt=0,m;
	while (1){
		scanf("%d",&n);
		if (!n) break;
		cin>>d>>k; m=n;
		memset(A,0,sizeof(A));
		while (k) A[m--]=k&1,k>>=1;
		
		printf("Case %d: ",++cnt);	
		cout<<DP()<<' '<<get_min()<<' '<<get_max()<<endl;
	}
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325935657&siteId=291194637