題意:給出3*k個數,每個數的範圍為[0,1000]。要求將其分為3個長度為k的序列,使得至少有兩個序列的和大於500*k。
思路:第一步的貪心比較好想,從大到小排序後後k個數捨棄不考慮。接下來的題意和雙機排程(和poj2576題意也比較相近,不過那道題揹包能過)有點像,就是讓2k個數分成兩份,每份k個數,使兩組數之和盡可能相近。當然首先想用揹包去做,但是一直wa(為啥不是tle呢??),於是看了題解原來是用隨機才能過,思路見**注釋即可。揹包能夠求出兩組數最相近的情況,複雜度比較高。而隨機只要符合題意就退出迴圈,所以會比揹包更快。
隨機的ac**:
#include #include #include #include #define max(a,b) ((a)<(b)?(a):(b))
#define n 62
struct nodes[n*3],t1[n],t2[n],q;
using namespace std;
int n,sum1,sum2;
bool cmp(struct node a,struct node b)
int main()
sort(s+1,s+1+3*n,cmp);//先從大到小排序,後n個不取必可構成最優
for(i = 1;i<=2*n;i++)else
}while(sum1<=500*n || sum2<=500*n)
for(i = 1;i<=n;i++)
printf("%d\n",t1[i].id);
for(i = 1;i<=n;i++)
printf("%d\n",t2[i].id);
for(i = 2*n+1;i<=3*n;i++)
printf("%d\n",s[i].id);
return 0;
}
揹包的wa:
#include #include #include #define n 62
struct nodes[n*3];
int dp[60005],p[n*2][60005],res1[n],res2[n];
using namespace std;
int n,len1,len2;
bool cmp(struct node a,struct node b)
void print(int d,int x)else
}int main()
sort(s+1,s+3*n+1,cmp);
for(i = 1;i<=2*n;i++)
sum += s[i].w;
dp[0] = 0;
memset(p, 0, sizeof(p));
for(i = 1;i<=sum/2;i++)
dp[i] = n+1;
for(i = 1;i<=2*n;i++)}}
for(j = 0;j=0;i--)
if(dp[i] != n+1)
break;
len1 = len2 = 0;
print(2*n,i);
for(i = 0;i
隨機化演算法
隨機化演算法的主要目的是希望讓隨機發生在演算法上,而不是發生在輸入分布上,這樣的話,沒有特別的輸入會引起我們的演算法的最壞情況。即使你最壞的敵人也無法產生最壞的輸入陣列。因為隨機排列使得輸入次序不再相關。只有在隨機數生成器產生乙個不走運的排列時,隨機演算法才會執行得很差。一.隨機優先順序陣列法 我們...
隨機化搜尋
參與考古挖掘的小明得到了乙份藏寶圖,藏寶圖上標出了 nn 個深埋在地下的寶藏屋,也給出了這 nn 個寶藏屋之間可供開發的mm 條道路和它們的長度。小明決心親自前往挖掘所有寶藏屋中的寶藏。但是,每個寶藏屋距離地面都很遠,也就是說,從地面打通一條到某個寶藏屋的道路是很困難的,而開發寶藏屋之間的道路 則相...
簡單隨機化
有乙個挺不錯的 隨機化blog codechef mstones 平面上有 n 個點 x i,y i 保證這 n 個點可以用 7 條直線覆蓋。找出一條直線使得它覆蓋的點最多 30 組 test n leq10 4 x i y i leq1.5 times10 4 每次隨機找兩個點 a,b 判斷它們所...