題目描述
jyx和cyy打賭,比誰24點算得快,算得慢的那個人請客。24點的規則是這樣的:給定4個1..9的整數,用括號改變運算順序,通過加、減、乘、除中的一系列運算,得到整數24。注意所有中間結果必須是整數(例如(2*2)/4是允許的,而2*(2/4)是不允許的)。爲了贏得這個比賽,請寫一個程序幫助我作弊,快速地計算出24點。
輸入輸出格式
輸入格式:一行4個整數,爲給定的4個數字。輸入數據保證有解。
輸出格式:一行,以字符串的形式輸出結果。注意將每一步的運算的括號補齊(例如(3+5)+6和3* (5+6))。如果有多種解答,輸出字典順序最小的一個。
輸入輸出樣例
題目很冗雜;
1/關於字典序的問題我們發現對括號有三種種情況:(((a+b)+c)+d)或((a+b)+(c+d))或(a+(b+(c+d))) 然後會發現第一種和第三種其實是完全等效的。左,中,右,三種;字典序優先,所以選擇第一種;
那麼有兩種入選(((a+b)+c)+d)或((a+b)+(c+d));
第一種是從頭到尾算下來,第二種先前兩個算,接着後兩個算,最後兩邊得到的結果算在一起;
兩種情況要分開打,麻煩沒辦法;
2/數字和運算符交替搜索是很難想到的;dfs中帶一個參數是選擇是數字還是字符的,如果是ture則爲數字,反之爲運算符;
3。用了哈希,搜索記錄的是運算符的下標;用一個函數來運算;
4/出現不能除進ruturn;
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int q1[20],q2[20];
char hash[5]={0,'*','+','-','/'};
int n[5];int used[5];
int operate(int a,int b,int c)
{
switch(c)
{
case 1:return a*b;
case 2:return a+b;
case 3:return a-b;
case 4:if(a%b==0)return a/b;else return -10;
}
return -10;
}
void dfs1(int u,bool o);
void dfs2(int u,bool o);
int main()
{
for(int i=1;i<=4;i++)scanf("%d",&n[i]);
sort(n+1,n+5);
dfs1(1,1);dfs2(1,1);
return 0;
}
void dfs1(int u,bool o)
{
if(u==8)
{
int ans=operate(q1[1],q1[3],q2[2]);
if(ans==-10)return ;
ans=operate(ans,q1[5],q2[4]);
if(ans==-10)return ;
ans=operate(ans,q1[7],q2[6]);
if(ans==24)
{
printf("(((%d%c%d)%c%d)%c%d)",q1[1],hash[q2[2]],q1[3],hash[q2[4]],q1[5],hash[q2[6]],q1[7]);
exit(0);
}
}
else
if(o)
{
for(int i=1;i<=4;i++)
if(!used[i])
{
q1[u]=n[i];
used[i]=1;
dfs1(u+1,!o);
used[i]=0;//!!!1
}
}
else
{
for(int i=1;i<=4;i++)
{
q2[u]=i;
dfs1(u+1,!o);
}
}
}
void dfs2(int u,bool o)
{
if(u==8)
{
int ans1=operate(q1[1],q1[3],q2[2]);
if(ans1==-10)return ;
int ans2=operate(q1[5],q1[7],q2[6]);
if(ans2==-10)return ;
int ans=operate(ans1,ans2,q2[4]);
if(ans==24)
{
printf("((%d%c%d)%c(%d%c%d))",q1[1],hash[q2[2]],q1[3],hash[q2[4]],q1[5],hash[q2[6]],q1[7]);
exit(0);
}
}
else
if(o)
{
for(int i=1;i<=4;i++)
if(!used[i])
{
q1[u]=n[i];
used[i]=1;
dfs2(u+1,!o);
used[i]=0;
}
}
else
{
for(int i=1;i<=4;i++)
{
q2[u]=i;
dfs2(u+1,!o);
}
}
}
親手打的,懶得標註了
題目描述
在一個長方形框子裏,最多有N(0≤N≤6)個相異的點,在其中任何一個點上放一個很小的油滴,那麼這個油滴會一直擴展,直到接觸到其他油滴或者框子的邊界。必須等一個油滴擴展完畢才能放置下一個油滴。那麼應該按照怎樣的順序在這N個點上放置油滴,才能使放置完畢後所有油滴佔據的總體積最大呢?(不同的油滴不會相互融合)
注:圓的面積公式V=pi*r*r,其中r爲圓的半徑。
輸入輸出格式
輸入格式:第1行一個整數N。
第2行爲長方形邊框一個頂點及其對角頂點的座標,x,y,x’,y’。
接下去N行,每行兩個整數xi,yi,表示盒子的N個點的座標。
以上所有的數據都在[-1000,1000]內。
輸出格式:一行,一個整數,長方形盒子剩餘的最小空間(結果四捨五入輸出)
輸入輸出樣例
因爲沒有單獨討論油滴在另一個油滴擴展的圓內的情況,這種情況就不能擴展,不單獨討論會變成負面積
#include<bits/stdc++.h>
using namespace std;
double dis[10][10],x,y,x2,y2,a[10][4];//a爲點的座標,1爲橫座標,2爲縱座標,dis油滴間距
double R[100],r,maxn;//r爲準備放置的油滴的擴散半徑 ,maxn是最大油麪積
int vis[100],n;//vis判斷是否走過
const double pi=acos(-1);
void dfs(int steps,double s)//steps位當前步數,s爲當前面積
{
if(steps==n+1)//油滴放完了
{ //更新最大值
if(s>maxn) maxn=s;}
else
for(int k=1;k<=n;k++)
if(!vis[k])//如果沒拜訪過
{
//矩形和已放置的油滴約束了r的大小 //fabs絕對值函數可以計算浮點數,好像abs不行
r=fabs(y2-a[k][2]);//縱座標邊框限制
//找到所有限制下的最小半徑
if(r>fabs(y-a[k][2]))r=fabs(y-a[k][2]);//另一邊
if(r>fabs(x2-a[k][1]))r=fabs(x2-a[k][1]);//其他邊框
if(r>fabs(x-a[k][1]))r=fabs(x-a[k][1]);//還是邊
for(int i=1;i<=n;i++)
{
if(vis[i])//如果拜訪過了
if(r>dis[k][i]-R[i])r=dis[k][i]-R[i];//其他油滴限制,油滴距離減去已存半徑
}
r=r<0?0:r; //r不能爲負
R[k]=r;//記錄半徑
//搜索模板
vis[k]=1;
dfs(steps+1,s+pi*r*r);
vis[k]=0;
R[k]=0.0;
}
}
int main()
{
scanf("%d%lf%lf%lf%lf",&n,&x,&y,&x2,&y2);
for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i][1],&a[i][2]);
//預處理出油滴間距dis
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
dis[i][j]=sqrt(pow(fabs(a[i][1]-a[j][1]),2)+pow(fabs(a[i][2]-a[j][2]),2));//油滴i和油滴j之間的間距,距離公式
dis[j][i]=dis[i][j];//i到j的距離就是j到i的距離
}
}
double S=fabs(x-x2)*fabs(y-y2);//矩形面積
dfs(1,0.0);
printf("%.0lf",floor(S-maxn+0.5));
return 0;
}