旅游论坛网站建设,h5游戏大厅,榆树网站建设,高清素材免费下载多米诺骨牌多米诺骨牌多米诺骨牌
Description Input
输入文件的第一行是一个正整数n(1≤n≤1000)#xff0c;表示多米诺骨牌数。接下来的n行表示n个多米诺骨牌的点数。每行有两个用空格隔开的正整数#xff0c;表示多米诺骨牌上下方块中的点数a和b#xff0c;且1≤a#…多米诺骨牌多米诺骨牌多米诺骨牌
Description Input
输入文件的第一行是一个正整数n(1≤n≤1000)表示多米诺骨牌数。接下来的n行表示n个多米诺骨牌的点数。每行有两个用空格隔开的正整数表示多米诺骨牌上下方块中的点数a和b且1≤ab≤6。
Output
输出文件仅一行包含一个整数。表示求得的最小旋转次数。
Sample Input
4
6 1
1 5
1 3
1 2
Sample Output 题目大意
有n个骨牌每个骨牌上面和下面都有一个1~6的数每个骨牌可以上下翻转使上下数字反转最少翻几次可以使上面数的总和与下面数的总和的差最少
解题思路
用一个二维数组f[i][j]来表示前i个骨牌上数减下数上数上面的数加在一起下数下面的数加在一起为j时翻转的最少次数每一个骨牌不翻时为-上面的数下面的数(因为递推要倒着推)翻时为上面的数-下面的数然后递推出结果
动态转移方程
f[i][j]min{f[i−1][j−a[i]b[i]]f[i−1][ja[i]−b[i]]1f[i][j]min\left\{\begin{matrix}f[i-1][j-a[i]b[i]]\\ f[i-1][ja[i]-b[i]]1\end{matrix}\right.f[i][j]min{f[i−1][j−a[i]b[i]]f[i−1][ja[i]−b[i]]1
第一次AC的代码
#includecstdio
#includeiostream
#includecstring
#define M 6000//设置上限
using namespace std;
int n,k,a[1002],b[1001],f[1001][12010];
int main()
{memset(f,127/3,sizeof(f));//用min时要先赋一个较大的值scanf(%d,n);f[0][M]0;//初值从0开始因为有负数所以从M开始上限是120006000下限是0-6000for (int i1;in;i)scanf(%d%d,a[i],b[i]);for (int i1;in;i)for (int j1;jM*2;j)//正负数都要f[i][j]min(f[i-1][j-a[i]b[i]],f[i-1][ja[i]-b[i]]1);//前面的是不翻后面的是翻k0;//从0开始while ((f[n][Mk]f[0][1])(f[n][M-k]f[0][1])) k;//f[0][1]为一开始的值有变化时说明可以翻成差值为kprintf(%d,min(f[n][Mk],f[n][M-k]));//输出最小的
}优化后的代码
#includecstdio
#includeiostream
#includecstring
using namespace std;
int n,M,k,a[1002],b[1001],f[1001][12005];
int main()
{memset(f,127/3,sizeof(f));scanf(%d,n);Mn*6;//变化主要有M因为大于n*6的都没有用所以这样可以省时间f[0][M]0;for (int i1;in;i){scanf(%d%d,a[i],b[i]);//塞在一起for (int jM-i*6;jMi*6;j)//第一次的范围是-6~6第二次是-12~12从M开始当i加一时上下的限制各加一可以省很多时间f[i][j]min(f[i-1][j-a[i]b[i]],f[i-1][ja[i]-b[i]]1);//动态转移方程}k0;//从0开始while ((f[n][Mk]f[0][1])(f[n][M-k]f[0][1])) k;//f[0][1]为一开始的值有变化时说明可以翻成差值为kprintf(%d,min(f[n][Mk],f[n][M-k]));//输出最小的
}