time limit: 1 second
memory limit: 128 mb
乘法難題是一種用一行的卡片來玩的單人遊戲,每張卡片上有乙個正整數。在遊戲者從中拿出一卡片,並且得到乙個分數,它等於被拿走的卡片上的數與這張卡片左右兩張卡片上的整數的積。第一張與與最後一張卡片不能被拿出。在最後一次移動後,這行卡片中只剩下兩張。 你的目標是怎樣確定拿卡片的順序,以使得總分數的值最小。例如,有一行的卡片,它上面的數字為10 1 50 20 5, 遊戲者可以先取走1這張卡片,然後是20 和50,總分數為10*1*50
+ 50*20*5 + 10*50*5 = 500+5000+2500 = 8000,如果他先拿50, 然接著20,最後取出1, 總分數為1*50*20 + 1*20*5 + 10*1*5 = 1000+100+50 = 1150。
輸入檔案的第一行包含卡片的總數n(3 <= n <= 100),第二行包含n個範圍在1到100之間的整數(兩個整數之間有乙個空格)
輸出檔案包含乙個整數,為最少的分數。
610 1 50 50 20 5
3650【題解】
設f[i][j]表示從i到j,除了i和j之外都被取走所能得到的最小分數。
f[i][j] = min(f[i][k]+f[k][j]+a[i]*a[k]*a[j]); i
初值:f[i][i+1] == 0;
更新方式如下:
for (int l=2;l<= n;l++)
for (int s = 1;s <= n-l;s++)
最後答案為f[1][n];
這裡一定要先列舉這段的長度。
這樣我們可以先獲得像f[1][3],f[2][4],f[3][5]..f[n-2][n]這樣的值。
然後我們在求f[1][4]的時候k在2..3列舉
f[1][4] = min(f[1][2]+f[2][4]+a[1]*a[2]*a[4],f[1][3]+f[3][4]+a[1]*a[3]*a[4]);
可以看到我們在求f[1][4]的時候要用到的f[2][4],f[1][3]都已經求出來了 。
這是原因所在。
也是這種型別動規的原理->不斷利用小的區間擴大區間。
【**】
#include #include int a[101],n,f[101][101];int main()
} printf("%d\n", f[1][n]);
return 0;
}