1. 程式人生 > >CSP考試 2013年12月第4題 有趣的數 C++實現

CSP考試 2013年12月第4題 有趣的數 C++實現

#include <stdio.h>
#include <string.h>
//挑戰程式設計競賽(第2版) 2.3.3 有關計數問題的DP
//感覺就像倒過來找
//錯誤 0分 修改 
//錯誤 0分 
//錯誤 20 
//30
//-879048156
//第一個動態規劃的程式 
//錯誤 40  
//60
//-609189446
int main()
{
	int NUM;
	scanf("%d",&NUM);
	long long dp[NUM+1][1<<3];//+20 long long 防溢位 
	memset(dp,0,sizeof(dp));
	int i;
	int j;//flag0flag1flag3
	dp[2][1]=1;//23  001
	dp[2][0]=1;//22  000
	dp[2][4]=1;//20  100
	dp[3][5]=2;//203 230   101
	dp[3][6]=1;//201   110
	for(i=0;i<=NUM;i++)//+20分 
	{
		for(j=0;j<1<<3;j++)
		{
			if((i>=4)&&(j==7))//111
			{
				dp[i][7]=(dp[i-1][7]*2//下一位只能選擇1或3 
				+dp[i-1][6]//下一位只能選擇3 110
				+dp[i-1][5])%1000000007;//下一位只能選擇1 101//%1000000007 +60
			}
			if((i>=3)&&(j==6)&&(i<NUM))//110 
			{
				dp[i][6]=(dp[i-1][6]*2//下一位只能選擇2或1 
				+dp[i-1][4])%1000000007;//下一位只能選擇1 100 
				//不可能 010
			}
			if((i>=3)&&(j==5)&&(i<NUM))//101
			{
				dp[i][5]=(dp[i-1][5]*2//下一位只能選擇0或3
				+dp[i-1][4]//下一位只能選擇3 100
				+dp[i-1][1])%1000000007;//只能選擇0 001 
			}
			if((i>=2)&&(j==4)&&(i<NUM-1))//100
			{
				dp[i][4]=(dp[i-1][4]*2//下一位只能選擇0或2 100
				//+dp[i-1][0];//下一位只能選擇0 000  dp[i-1][0]==1 
				+1)%1000000007;
			}
			if((i>=2)&&(j==1)&&(i<NUM-1))//001
			{
				dp[i][1]=(dp[i-1][1]//下一位只能選擇3 001
				//+dp[i-1][0];//下一位只能選擇3 000   dp[i-1][0]==1 
				+1)%1000000007;
			}
		}
	}
	printf("%d",dp[NUM][7]);
	return 0;
} 

下面是同一個問題的另一個程式。執行超時,20分。

#include <stdio.h>
//一位一位的算
// 執行超時 20 
//已經剪枝了 

//挑戰程式設計競賽(第2版) 2.3.3 有關計數問題的DP
//感覺就像倒過來找 
	void DFS(int& total,int NUM,int n,int flag0,int flag1,int flag3)//減少到兩個變數 n和flag0flag1flag3 P54從記憶搜尋出發推匯出遞推式  
	{
		//printf("%d %d %d %d %d\n",n,flag0,flag1,flag3,total);
		if((n==NUM)&&(flag0==1)&&(flag1==1)&&(flag3==1))
		{
			total++;
		}
		if(n==NUM)
		{
			return;
		}
		int _flag0=flag0;
		int	_flag1=flag1;
		int	_flag3=flag3;
		if((flag1==0)&&(flag3==1))//1沒有出現過3出現過可以選擇0,1,3 
		{
			flag0=1;//這一位選擇0
			DFS(total,NUM,n+1,flag0,flag1,flag3); 
			flag0=_flag0;
			flag1=_flag1;
			flag3=_flag3;
			flag1=1;//選擇1
			DFS(total,NUM,n+1,flag0,flag1,flag3); 
			flag0=_flag0;
			flag1=_flag1;
			flag3=_flag3; 
			flag3=1;//選擇3 
			DFS(total,NUM,n+1,flag0,flag1,flag3);
		}else if((flag1==1)&&(flag3==0))//1出現過3沒有出現過可以選擇2,1, 3 
		{
			//flag2=1;//這一位選擇2
			DFS(total,NUM,n+1,flag0,flag1,flag3); 
			flag0=_flag0;
			flag1=_flag1;
			flag3=_flag3;
			flag1=1;//選擇1
			DFS(total,NUM,n+1,flag0,flag1,flag3); 
			flag0=_flag0;
			flag1=_flag1;
			flag3=_flag3;
			flag3=1;//選擇3
			DFS(total,NUM,n+1,flag0,flag1,flag3); 
		}else if((flag1==0)&&(flag3==0))//1沒出現過3沒出現過可以選擇 0,1,2, 3 
		{
			//選擇0
			flag0=1;
			DFS(total,NUM,n+1,flag0,flag1,flag3); 
			flag0=_flag0;
			flag1=_flag1;
			flag3=_flag3;
			flag1=1;//選擇1
			DFS(total,NUM,n+1,flag0,flag1,flag3); 
			flag0=_flag0;
			flag1=_flag1;
			flag3=_flag3;
			//選擇2
			DFS(total,NUM,n+1,flag0,flag1,flag3); 
			flag0=_flag0;
			flag1=_flag1;
			flag3=_flag3; 
			flag3=1;//選擇3 
			DFS(total,NUM,n+1,flag0,flag1,flag3);
		}else if((flag1==1)&&(flag3==1))//1出現過3出現過可以選擇1, 3 
		{
			flag1=1;//選擇1
			DFS(total,NUM,n+1,flag0,flag1,flag3);
			flag0=_flag0;
			flag1=_flag1;
			flag3=_flag3; 
			flag3=1;//選擇3 
			DFS(total,NUM,n+1,flag0,flag1,flag3);
		} 
	}
int main()
{
	int NUM;
	scanf("%d",&NUM);
	NUM=NUM-1;//第一位一定是2 
	int total=0;

	DFS(total,NUM,0,0,0,0); 
	printf("%d",total%1000000007);
	return 0; 
}