H卡迪亞的遊戲
這題一看,零一揹包的皮,然後無論是回溯做法的O(2^n)還是正常dp的O(VN)都滿足不了這些毒瘤數據,過於生草,然後神勇的隊友竟然設dp[i][j]爲前i個物品價值爲j的情況下的最小重量。時間複雜度一下子變成O(n*價值最大值),才1e4。
代碼:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int w[105],v[105];
int dp[105][10005];
int main(){
int n,W;
scanf("%d %d",&n,&W);
for (int i=1;i<=n;i++)
scanf("%d %d",&w[i],&v[i]);
for (int i=0;i<=n;i++)
for (int j=0;j<=n*100;j++)
dp[i][j]=inf;
dp[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=n*100;j++)
dp[i][j]=min(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
}
int ans=0;
for(int i=0;i<=n*100;i++)
if (dp[n][i]<=W) ans=i;
printf("%d",ans);
}
F我要去看流星雨
這個題可以先找有哪幾對點滿足引力差不大於M的,也可以先找相鄰點;最後來一個並查集求聯通塊就行了。師兄先找後者,他說散列再散列,然後給出華麗的code說:“stl大賽”
師兄的做法和我是殊途同歸的,我先求引力差不超過M的pair,這個求法就很好求了,開一個結構體按照v大小sort一下就行了,用Next數組來標記當前點滿足引力差小於等於M的點區間是多少,因爲代碼有點長就註釋了一下,看註釋問題不大就不細說。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <queue>
#include <stack>
#include <map>
//
using namespace std;
const int INF = 0x3f3f3f3f;//1.06e9大小
const int mod1 = 1e9 + 7;
const int mod2 = 998244353;
const int mod3 = 1e9;
const double PI = 3.14159265;
const double eps =1e-8;
typedef unsigned long long ULL;
typedef long long LL;
//
struct note
{
int x,y,z,v;
};
note a[10001];
int fa[10001];
int Next[10001];
int tong[10001];
bool cmp(note x,note y)
{
return x.v>y.v;
}
int getfa(int k)
{
return fa[k]==k?k:fa[k]=getfa(fa[k]);
}
void mer(int x,int y)
{
int a=getfa(x);
int b=getfa(y);
fa[a]=b;
}
bool check(int i,int j)
{
int cnt=0;
int flag=0;
if(a[i].x==a[j].x)++cnt;
if(a[i].y==a[j].y)++cnt;
if(a[i].z==a[j].z)++cnt;
if(abs(a[i].x-a[j].x)==1)flag=1;
if(abs(a[i].y-a[j].y)==1)flag=1;
if(abs(a[i].z-a[j].z)==1)flag=1;
if(cnt==3)return true;
if(cnt==2&&flag)return true;
return false;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;++i)fa[i]=i;
for(int i=1;i<=n;++i)
{
scanf("%d %d %d %d",&a[i].x,&a[i].y,&a[i].z,&a[i].v);
}
sort(a+1,a+1+n,cmp);
int j=2;
for(int i=1;i<=n;++i)
{
while(j!=n+1&&a[i].v-a[j].v<=m)++j;
Next[i]=j;//求第i個點i能和(i,j)區間之間的點鏈接.
}
for(int i=1;i<n;++i)
{
for(int j=i+1;j<Next[i];++j)
{
if(check(i,j))mer(i,j);//鏈接所有引力差小於等於m同時相鄰的點。
}
}
int cnt=0;//連通塊的數量;
int MAX=0;
for(int i=1;i<=n;++i)
{
if(tong[getfa(i)]==0)++cnt;
tong[getfa(i)]++;
MAX=max(MAX,tong[getfa(i)]);
}
printf("%d %d\n",cnt,MAX);
return 0;
}