10.23爆零了竟然還能寫題解??
10.23爆零題解
T1超級大水題,結果忘了輸出“\n”,爆零;
T2網路流+二分,結果忘了memcpy(),爆零;
T3,嗯,不會。
T1. LMY與LYM
問題描述:
LMY與LYM在玩一個數字遊戲,一開始黑板上寫有兩個整數n,m。LMY先手,LMY和LYM輪流操作,每人都可以將當前的n加上n的一個正因數d,變成n+d,第一個將n變成一個大於m的數的人輸掉比賽。現在給出兩個數n,m;LMY和LYM都非常聰明,問誰會獲勝?
輸入:
有多組測試資料:
第一行一個整數T,表示有T組資料。
第二行到第T+1行,每行兩個整數,分別表示n,m。
輸出:
輸出T行,若LMY贏,輸出“LMY beats LYM”; 若LYM贏,輸出“LYM beats LMY”;
樣例輸入輸出:
1
2 3LMY beats LYM
資料範圍:
30%資料: T<10; n<10;m<100;
100%資料:T<=213;n<=231-1, n
#include<iostream>
using namespace std;
long long n,m,T;
int main()
{
//freopen("lmym.in","r",stdin);
//freopen("lmym.out","w",stdout);
scanf("%lld",&T);
for (int i=1;i<=T;i++)
{
scanf("%lld%lld",&n,&m);
if(n&1)printf("LYM beats LMY\n");
else printf("LMY beats LYM\n");
}
}
題解:此題極水,上個廁所隨便列舉幾個數就找到規律,就只需要判斷奇偶即可,不要忘了換行TAT。
T2. 河城荷取
問題描述:
在幻想鄉,河城荷取是擅長高科技工業的河童。荷取的得意之作是巨型人形機械『非想天則』。不過由於人形太過巨大,所以為它充能是一件很麻煩的事。
人形一共有 N 個電能池,編號 1..N。其中前 L 個電能池(即編號為 1..L 的電能池)連線著外部充能介面,而編號為 N 的電能池連線著動力爐核心。在 N 個蓄能池之間有 M 條單向管道,每條管道有一個啟用代價cost和電能傳輸極限limit。當啟用度達到某個值時,所有啟用代價小於等於這個值的管道都會被啟用,但是每一條管道一時只能夠最多傳送 limit個單位的電能。外部介面到電能池和電能池到動力爐核心的管道傳輸沒有限制並且啟用代價為 0。現在荷取想往動力爐核心輸入至少K個單位的電能,求需要的最小啟用度。
輸入:
第 1 行:4 個正整數 N,M,L, K
第 2..M+1 行:4 個整數,u,v,limit,cost,表示一條由 u 到 v 的管道,傳輸極限 limit,啟用代價 為 cost
輸出:
第 1 行:1 個整數,表示最小啟用代。
樣例輸入:
6 5 3 3
1 4 2 4
2 4 3 5
3 5 4 2
4 6 2 3
5 6 3 44
樣例說明:
資料範圍:
對於 30%的資料:1 ≤ L ≤ N ≤ 100,0 ≤ M ≤ 2,000,1 ≤ cost ≤ 10,000
對於 60%的資料:1 ≤ L ≤ N ≤ 1,000,0 ≤ M ≤ 20,000,1 ≤ cost ≤ 10,000
對於 100%的資料:1 ≤ L ≤ N ≤ 2,000,0 ≤ M ≤ 80,000,1 ≤ cost ≤ 1,000,000
對於 100%的資料:1 ≤ limit ≤ 1,000
保證任意(u,v)都只出現一次。
題解:建圖網路流,二分列舉最大花費,每次討論要重新讀圖!;
程式碼如下:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int inf=1e9,maxn=2017,maxm=80050;
int ma[maxn][maxn],g[maxn][maxn],c[maxn][maxn],cnt[maxm],dis[maxm],flow,ans;
int n,m,L,k,lim,cos,x,y,st,maxx=0,w[maxm],xxx;
inline void re(int &d)
{
bool f=false;char t=getchar();
while(t<'0'||t>'9'){if(t=='-')f=true;t=getchar();}
for(d=0;t>='0'&&t<='9';t=getchar())d=(d<<1)+(d<<3)+t-'0';
d=(f?(-d):(d));
}
int dfs(int u,int flow,int maxcost){
int v,temp,delta=0;
if(u==n)return flow;
for(v=1;v<=n;v++){
if(g[u][v]&&dis[u]==dis[v]+1&&c[u][v]<=maxcost)
{
temp=dfs(v,min(flow-delta,g[u][v]),maxcost);
g[u][v]-=temp;
g[v][u]+=temp;
delta+=temp;
if(delta==flow||dis[st]>=n)return delta;
}
}
if(dis[st]>n)return delta;
cnt[dis[u]]--;
if(cnt[dis[u]]==0)dis[st]=n;
dis[u]++;
cnt[dis[u]]++;
return delta;
}
bool ok(int x)
{
memcpy(g,ma,sizeof(ma));
memset(cnt,0,sizeof(cnt));
memset(dis,0,sizeof(dis));
int tmp,ans=0;
while(dis[st]<n)
{
tmp=dfs(st,inf,x);
ans+=tmp;
}
if(ans>=k)return true;
else return false;
}
void work1()
{
int l=0,r=m,mid;
while(l<=r)
{
mid=(l+r)>>1;
if(ok(w[mid]))r=mid-1;
else l=mid+1;
}
xxx=l;
}
int main()
{
st=0;
re(n);re(m);re(L);re(k);
for(int i=1;i<=m;i++)
{
re(x);re(y);re(lim);re(cos);
ma[x][y]=lim;
w[i]=c[x][y]=cos;
}
for(int i=1;i<=L;i++)ma[0][i]=inf,c[0][i]=0;
sort(w+1,w+1+m);
work1();
printf("%d",w[xxx]);
}
T3. 最短路徑
問題描述:
平面內給出 n 個點,記橫座標最小的點為 A,最大的點為 B,現在小 Y 想要知道在 每個點經過一次(A 點兩次)的情況下從 A 走到 B,再回到 A 的最短路徑。但他是個強迫症患者,他有許多奇奇怪怪的要求與限制條件:
1.從 A 走到 B 時,只能由橫座標小的點走到大的點。
2.由 B 回到 A 時,只能由橫座標大的點走到小的點。
3.有兩個特殊點 b1 和 b2, b1 在 0 到 n-1 的路上,b2 在 n-1 到 0 的路上。 請你幫他解決這個問題助他治療吧!
樣例輸入輸出:
5 1 3
1 3
3 4
4 1
7 5
8 318.18
程式碼。。。如下:
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1007,inf=1e9;
struct point{
int x;int y;
}poi[maxn];
double dis(int a,int b)
{
return sqrt((poi[a].x-poi[b].x)*(poi[a].x-poi[b].x)+(poi[a].y-poi[b].y)*(poi[a].y-poi[b].y));
}
double f[maxn][maxn];
int n,b1,b2,i,j;
int main()
{
memset(f,0x7f,sizeof(f));f[1][1]=0;
scanf("%d%d%d",&n,&b1,&b2);
b1++;b2++;
for(i=1;i<=n;i++)scanf("%d%d",&poi[i].x,&poi[i].y);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==1||i!=j)
{
int k=1;
double tmp;
k+=max(i,j);
if(k==n+1)
{
if(j==n)
{
tmp=dis(i,n);
f[n][n]=(f[n][n]<tmp?(f[n][n]):(f[i][j]+tmp));
}
else if(i==n)
{
tmp=dis(j,n);
f[n][n]=(f[n][n]<tmp?(f[n][n]):(f[i][j]+tmp));
}
continue;
}
if(k!=b1)f[i][k]=min(f[i][k],f[i][j]+dis(j,k));
if(k!=b2)f[k][j]=min(f[k][j],f[i][j]+dis(i,k));
}
printf("%.2lf",f[n][n]);
}