CSP考試 2013年12月第4題 有趣的數 C++實現
阿新 • • 發佈:2019-02-14
#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; }